When a function that is accepting a list of a base class (for example class Base) is passed and argument which is a list of subclass instances of the base class (for example Thing(Base)) mypy complains about incompatible type: Error: Argument 1 to "function" has incompatible type List[Thing]; expected List[Base].
Wrapping the argument with a cast to a list of the base class passes.
Code example:
from typing import List, cast
class Base:
pass
class Thing(Base):
pass
def function(arg: List[Base]) -> None:
pass
things:List[Thing] = [Thing()]
# Error: Argument 1 to "function" has incompatible type List[Thing]; expected List[Base]
function(things)
# Passes
function(cast(List[Base], things))
This is as designed, please read up on Liskov.
You can often use Sequence[x] instead of List[x] to get code like your example working. This works because Sequence is covariant and doesn't let you set items in the list, unlike List[x] which is invariant and allows the mutation of the list.
This is expected behavior and documented at http://mypy.readthedocs.io/en/latest/generics.html#variance-of-generic-types. Your example would fail with code like this:
things: List[Thing] = []
def function(arg: List[Base]) -> None:
arg.append(Base())
function(things)
for thing in things:
assert isinstance(thing, Thing) # fails at runtime, but type checker detects no errors
If your function doesn't actually modify the list, you can get around this error by typing the argument as Sequence[Base] or even Iterable[Base] instead.
Most helpful comment
This is expected behavior and documented at http://mypy.readthedocs.io/en/latest/generics.html#variance-of-generic-types. Your example would fail with code like this:
If your function doesn't actually modify the list, you can get around this error by typing the argument as
Sequence[Base]or evenIterable[Base]instead.