Consider a function that performs type promotion, e.g. a simple multiplication of two numbers that can both be either int
or float
:
def mul(a: int | float, b: int | float): # return type? return a * b
This function returns float
, except in the case where both a
and b
are int
.
How can I properly and concisely annotate the return type? I know I can do this with @overload
:
from typing import overload@overloaddef mul(a: int, b: int) -> int: ...@overloaddef mul(a: float, b: int | float) -> float: ...@overloaddef mul(a: int | float, b: float) -> float: ...def mul(a, b): return a * b
but this is very verbose and requires many overloads for something I would imagine some "type function" should handle. In C++ this could be done e.g. with SFINAE. Is there something similar I can do in Python in terms of a generic function along the lines of
def mul(a: T1, b: T2) -> promote_types(T1, T2): return a * b
that also works with TypeVars? I don't expect anything built in that already works for int
and float
, but some technique perhaps?
Notes:
I know about the recommendation to just annotate everything taking an
int
withfloat
, but my setting has more complicated TypeVars, the choice ofint
andfloat
here is just a simple example.I know I can just do
Union[int, float]
, but I need it to be specific. Depending on the exact types the function is called with, the return type must be exact too, not a union.