I have the following simple classes
class A:
pass
class B(A):
pass
I want another class, C
, with a method which will accept as an argument any subclass of A
, which will default to B
. I thought a Generic
would be a suitable candidate here:
T = TypeVar('T', bound=A)
class C(Generic[T]):
def foo(self, assistant: type[T] = B) -> None:
pass
However, when I run mypy I get the error
Incompatible default for argument "assistant" (default has type "type[B]", argument has type "type[T]"
I find this a little confusing, as I thought the idea of TypeVar('T', bound=A)
was to create a type compatible with any subclass of A
(so in particular B
).
Does anyone know what I'm doing wrong here?
You don't need generics. You should just do
class C:
def foo(self, assistant: type[A] = B) -> None:
...
type[A]
is already the type representing all classes that descend from A
(including A
).
What you've done is create a generic class. That class takes type parameters, like c: C[B] = C()
, and the argument to foo
must be a descendant of whatever the type parameter was.
With your class definition, if you did
class D(A): pass
c: C[D] = C()
then c.foo
would require a descendant of D
as an argument. However, the default value B
is not a descendant of D
, so the default value would be an invalid argument, hence the error message.