This answer does not seem to work for generics. Mypy complains about "error: Missing type parameters for generic type A" when checking the following code. I have tried using 'A[T]'
for the TypeVar but then mypy says "error: Type variable T is unbound." I have also tried using AnyA[T]
as return type of get
but that produces two error messages, the already known "error: Missing type parameters for generic type A" and the new error message "Type variable AnyA used with arguments".
How do I specify the return type of get
correctly?
import typing
T = typing.TypeVar('T')
AnyA = typing.TypeVar('AnyA', bound='A')
class A(typing.Generic[T]):
def __init__(self, val: T) -> None:
self.val = val
def get(self: AnyA) -> AnyA:
return self
class B(A[T]):
def is_int(self) -> bool:
return isinstance(self.val, int)
if __name__ == '__main__':
b = B(42)
print(b.get().is_int())
CodePudding user response:
I know of three ways of typing here:
Declaring an inner self-type
This approach is described in mypy
docs, see Precise typing of alternative constructors.
class A(typing.Generic[T]):
_Self = typing.TypeVar('_Self', bound='A[T]')
def __init__(self, val: T) -> None:
self.val = val
def get(self: _Self) -> _Self:
return self
Note however, that this is mypy
-specific stuff and may not work with other checkers. E.g. pyre
doesn't support inner self-types yet.
Using _typeshed.Self
This saves the boilerplate of declaring custom types, but requires a somewhat obscure import from typeshed which will fail at runtime. It thus must be wrapped by typing.TYPE_CHECKING
:
from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
from _typeshed import Self
else:
Self = Any
class A(typing.Generic[T]):
def __init__(self, val: T) -> None:
self.val = val
def get(self: Self) -> Self:
return self
_typeshed.Self
was created to be used in custom stubs in the first place, but is suitable for inline typing as well.
Python 3.11 and upwards: typing.Self
A recently introduced PEP 673 adds Self
to stdlib, so starting from Python 3.11 one will be able to use that:
from typing import Self
class A(typing.Generic[T]):
def __init__(self, val: T) -> None:
self.val = val
def get(self: Self) -> Self:
return self
This is not supported by mypy
yet as of now though, but e.g. by pyright
from version 1.1.184.