-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
bugmypy got something wrongmypy got something wrong
Description
from typing import Optional, TypeVar
U = TypeVar('U', bound=Optional[int])
def f(u: U) -> U:
if u is None:
return None
assert isinstance(u, int) # removing this line causes it to pass.
return uGives
main.py:10: error: Incompatible return value type (got "int", expected "U")
I cannot remove the assertion since it stands in for other code that is effectively constraining u.
This can be expressed tediously using overload:
from typing import Optional, TypeVar, overload
@overload
def f(u: None) -> None: ...
@overload
def f(u: int) -> int: ...
def f(u: Optional[int]) -> Optional[int]:
if u is None:
return None
assert isinstance(u, int)
return uWould it be possible to get the TypeVar approach to pass? It is far more succinct, and this quickly blows up in complexity if there are more argument-return type constraints to be enforced.
This pattern is analogous to the common class factory pattern:
class C: pass
class B(C): pass
class A(B): pass
T = TypeVar('T', bound=C)
def factory(cls: Type[T]) -> T:
return cls()Since A < B < C, this enforces
factory(Type[C]) -> C
factory(Type[B]) -> B
factory(Type[A]) -> A
This issue argues that since int < Optional[int] and None < Optional[int], we should ideally be able to similarly specify that
f(int) -> int
f(None) -> None
using the same notation.
aucampia and bcmillsaucampia
Metadata
Metadata
Assignees
Labels
bugmypy got something wrongmypy got something wrong