Its better to overload python function covariants instead Unionizing them for higher precision
When a function can accept different types and returns different types based on the input, using @overload provides more precise type hints than using Union types. This helps type checkers like mypy understand the exact return type for each input type.
The problem with Union:
from typing import Union
def process(x: Union[int, str]) -> Union[int, str]:
if isinstance(x, int):
return x * 2
return x.upper()
# Type checker can't determine the precise return type
result = process(5) # Could be int or str, mypy doesn't know which
The solution with @overload:
from typing import overload
@overload
def process(x: int) -> int: ...
@overload
def process(x: str) -> str: ...
def process(x):
if isinstance(x, int):
return x * 2
return x.upper()
result = process(5) # Type checker knows this is int
text = process("hello") # Type checker knows this is str
With @overload, type checkers can provide accurate autocompletion and catch type errors that would slip through with Union types. Each overload signature precisely describes one specific input-output relationship.