Currently mypy doesn't complain about this code:
from typing import Type
class A:
def __init__(self, x: int) -> None: pass
def f(t: Type[object]) -> None:
t() # ok, since `object()` is valid
f(A) # no error reported!
This is caused by __init__ overrides not needing to be compatible with base classes.
It's not clear how to type check such code. Here are some ideas, some of which have been discussed before:
- We could reject calling
Type[C] and require Type[[ArgType, ...], C] for type objects that can be called. The argument types would specify a signature for __init__. This would require a PEP 484 (and a typing change). This has the problem of being backward incompatible. Additionally, it's not clear how to specify signatures with keyword arguments or optional arguments.
- Similar to above, but by default
Type[C] would take the __init__ signature from C, similar to how it behaves now. Unlike now, Type[D] would only be a subtype of Type[C] if the __init__ signature is compatible. Type[None, C] would be a type object that is not callable. Type[[X, ...], C] would also be supported and would support specifying a specific signature instead of just taking it from C.
Type[..., C] would be a callable type object which accepts arbitrary arguments.
Type[[T], C[T]] would perhaps also be valid for generic classes (T is a type variable).
Class methods also have this issue. We could support specifying the type of cls explicitly. For example:
class A:
...
@classmethod
def f(cls: Type[[int], A]) -> A:
return cls(1) # ok
(I known that this is an old issue, but I couldn't find a previous open issue.)
Currently mypy doesn't complain about this code:
This is caused by
__init__overrides not needing to be compatible with base classes.It's not clear how to type check such code. Here are some ideas, some of which have been discussed before:
Type[C]and requireType[[ArgType, ...], C]for type objects that can be called. The argument types would specify a signature for__init__. This would require a PEP 484 (and atypingchange). This has the problem of being backward incompatible. Additionally, it's not clear how to specify signatures with keyword arguments or optional arguments.Type[C]would take the__init__signature fromC, similar to how it behaves now. Unlike now,Type[D]would only be a subtype ofType[C]if the__init__signature is compatible.Type[None, C]would be a type object that is not callable.Type[[X, ...], C]would also be supported and would support specifying a specific signature instead of just taking it fromC.Type[..., C]would be a callable type object which accepts arbitrary arguments.Type[[T], C[T]]would perhaps also be valid for generic classes (Tis a type variable).Class methods also have this issue. We could support specifying the type of
clsexplicitly. For example:(I known that this is an old issue, but I couldn't find a previous open issue.)