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 * bThis 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 * bbut 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 * bthat 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
intwithfloat, but my setting has more complicated TypeVars, the choice ofintandfloathere 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.