Reputation: 5877
$ cat foo.py
from typing import overload, Union, TypeVar
T = Union[int, str]
SubT = TypeVar("SubT", int, str)
@overload
def a(t: T) -> T:
...
@overload
def a(t: SubT) -> SubT:
...
def a(t: T) -> T:
return t
$ mypy foo.py
foo.py:7: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
Why are the return types incompatible, and how can I make this typecheck? I want these example return types:
v_1: Union[int, str] = 1
v_2: int = 2
v_3: str = "3"
a(v_1) # Want Union[int, str].
a(v_2) # Want int.
a(v_3) # Want str.
I want to avoid having to explicitly overload a
for int
and str
, as SubT
has many more than 2 constraints in reality.
If I remove the first overload, a(v_1)
wouldn't type check. If I remove the second overload, a(v_2)
and a(v_3)
would have their return value type hinted as Union[int, str]
instead of int
and str
respectively.
In my actual problem, I have an Iterable
of either homogeneous types under SubT
(the TypeVar
) or heterogeneous types under T
(the Union
). I want to write an a
that will operate on the elements of both without losing type granulariy if it present in the homogeneous case.
Upvotes: 1
Views: 900
Reputation: 224862
TypeVar
will let you offer both the types of the union and the union itself as options:
T = TypeVar("T", int, str, Union[int, str])
def a(t: T) -> T:
return t
Upvotes: 1