fromtypingimportOptional, TypeVarU=TypeVar('U', bound=Optional[int])
deff(u: U) ->U:
ifuisNone:
returnNoneassertisinstance(u, int) # removing this line causes it to pass.returnuGives
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:
fromtypingimportOptional, TypeVar, overload@overloaddeff(u: None) ->None: ...
@overloaddeff(u: int) ->int: ...
deff(u: Optional[int]) ->Optional[int]:
ifuisNone:
returnNoneassertisinstance(u, int)
returnu
Would 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:
classC: passclassB(C): passclassA(B): passT=TypeVar('T', bound=C)
deffactory(cls: Type[T]) ->T:
returncls()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.
Gives
I cannot remove the assertion since it stands in for other code that is effectively constraining
u.This can be expressed tediously using
overload:Would it be possible to get the
TypeVarapproach 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:
Since A < B < C, this enforces
This issue argues that since int < Optional[int] and None < Optional[int], we should ideally be able to similarly specify that
using the same notation.