pythonmypytypinginvariance

Mypy: how to specify list (or sequence) of mixed types?


Here some code:

import typing

class A:
    def f(self):
        print("A")

class B:
    def f(self):
        print("B")

C = typing.Union[A,B]
Sequence_C = typing.Sequence[C]

a = A()
b = B()

d : Sequence_C = [a]+[b]

mypy provides this error:

error: List item 0 has incompatible type "B"; expected "A"

My (possibly incorrect) undestanding:

C = typing.Union[A,B]
Sequence_C = typing.Sequence[C]

means that instances of Sequence_C are either sequences of instances of A or sequences of instances of B.

I would like to create a type Sequence_C which are sequences of instances of both A and B.

My motivation is that I need a list of instances implementing a "f" method.

Note that being more explicit did not help:

import typing

class S:
    def f(self):
        raise NotImplementedError()

class A(S):
    def f(self):
        print("A")

class B(S):
    def f(self):
        print("B")

Sequence_S = typing.Sequence[S]

a = A()
b = B()

d : Sequence_S = [a]+[b]

(same error)


Solution

  • You need to tell the type checker that [a] and [b] are to be interpreted as Sequence_S, and not typing.Sequence[A] (or [B]) explicitly, e.g. like this:

    import typing
    
    class S:
        def f(self) -> None:
            raise NotImplementedError()
    
    class A(S):
        def f(self) -> None:
            print("A")
    
    class B(S):
        def f(self) -> None:
            print("B")
    
    Sequence_S = typing.Sequence[S]
    
    a: Sequence_S = [A()]
    b: Sequence_S = [B()]
    
    # Sequences don't support "+", see https://docs.python.org/3/glossary.html#term-sequence
    d : Sequence_S = [*a, *b]