Consider a simple pair of generic classes:
T = TypeVar("T", str, int)
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
While using T = TypeVar("T")
works as expected. The restricted TypeVar
as shown yields the following errors:
error: Argument 1 to "__init__" of "Base" has incompatible type "str"; expected "T"
error: Argument 1 to "__init__" of "Base" has incompatible type "int"; expected "T"
note: Revealed type is 'builtins.int*'
Note that reveal_type
still works.
Another difference, is that the restricted TypeVar
requires the type annotation for self.v
assignment whereas the unrestricted does not.
In the full use-case, I actually have Callable[[Any], T]
, but the issue is the same.
This is with mypy 0.910
and Python 3.9.7
.
Bounding T
to an Union[int,str]
should do the job:
T = TypeVar("T", bound=Union[str, int])
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
y = Child('a')
reveal_type(y.value)
This seems to happen anytime you call super()
and pass the a generic restricted TypeVar
argument to any function not just init. On those cases, I believe we can ask mypy to leave this poor thing as it is, by including # type: ignore
in those lines:
...
super().__init__(v) # type: ignore
...
It is not so bad as it seems because type checking will still be done on other lines, differently of what would happen if you remove the : T
from the parameter on parent function or on the child function (any of those would suffice to suppress complains, but would also stop checking inside those functions as well).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With