-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Description
If I create an alias for a generic type using a TypeVar, Mypy seems to infer the TypeVar as Any and lose the typing information. For example, this works:
from typing import TypeVar, Callable
T = TypeVar('T')
def wrapper(func: Callable[[], T]) -> T:
reveal_type(func)
reveal_type(func())
return func()and gives these types:
mypy --strict generic_callable.py
generic_callable.py:7: error: Revealed type is 'def () -> T`-1'
generic_callable.py:8: error: Revealed type is 'T`-1'
I would expect this
from typing import TypeVar, Callable
T = TypeVar('T')
C = Callable[[], T]
def wrapper(func: C) -> T:
reveal_type(func)
reveal_type(func())
return func()to behave in the same way, but it doesn't:
mypy --strict generic_callable.py
generic_callable.py:8: error: Revealed type is 'def () -> Any'
generic_callable.py:9: error: Revealed type is 'Any'
generic_callable.py:10: warning: Returning Any from function declared to return "T"
This can be a problem if I am using the same complex generic type multiple times, as in this real-world example:
import functools
import warnings
from typing import Callable, TypeVar
_ReturnType = TypeVar('_ReturnType')
_CallableType = Callable[..., _ReturnType]
def deprecated(msg: str) -> Callable[[_CallableType], _CallableType]:
def outer_wrapper(func: _CallableType) -> _CallableType:
@functools.wraps(func)
def inner_wrapper(*args: object, **kwargs: object) -> _ReturnType:
warnings.simplefilter('always', DeprecationWarning)
warnings.warn(f"{func.__name__} is deprecated: {msg}.",
category=DeprecationWarning,
stacklevel=2)
warnings.simplefilter('default', DeprecationWarning) # reset filter
return func(*args, **kwargs)
return inner_wrapper
return outer_wrapperwhich gives:
mypy --strict test_deprecated.py
test_deprecated.py:18: warning: Returning Any from function declared to return "_ReturnType"
Having to explicitly type out Callable[..., _ReturnType] everywhere I use _CallableType would be a little cumbersome in this case.