Open fofoni opened 1 day ago
As a workaround, you can try giving _T
a default type argument. For example:
_T = TypeVar("_T", covariant=True, default=int)
reveal_type(decorator_factory()) # N: "def [_P] (def (*_P.args, **_P.kwargs) -> builtins.int) -> def (*_P.args, **_P.kwargs) -> builtins.int"
reveal_type(Class.method_one) # N: "def (self: SCRATCH.Class) -> builtins.int"
reveal_type(Class().method_one()) # N: "builtins.int"
Using default=Any
or default=object
would also work, depending on what makes the most sense in your application.
For the record, while pyright doesn't complain, it's just as confused as mypy about how to bind _T
, just silently so :wink::
# pyright 1.1.389
reveal_type(decorator_factory()) # Type of "decorator_factory()" is "((**_P@decorator_factory) -> Unknown) -> ((**_P@decorator_factory) -> Unknown)"
reveal_type(Class.method_two) # Type of "Class.method_two" is "(self: Class) -> Unknown"
reveal_type(Class().method_two()) # Type of "Class().method_two()" is "Unknown"
while pyright doesn't complain, it's just as confused as mypy
Pyright is not confused here; it's working correctly. It binds the TypeVar based on the default value Box
which is equivalent to Box[Unknown]
. (Pyright uses Unknown
to refer to an implied Any
.)
In the second call to
decorator_factory()
with no arguments,_T
should be bound toint
. I understand that inferring _T=int is maybe too much for mypy, but I believe_T
should then be bound toAny
, or maybeobject
to be extra strict, but definitely notNever
, which is what currently happens.https://mypy-play.net/?mypy=master&python=3.13&gist=4a1aeecb04582945c4fa78f196bace5f
For the record, pyright has no complaints about this code.