Common mistakes
Overload stubs without an implementation
from typing import overload
@overload
def double(value: int) -> int: ...
@overload
def double(value: str) -> str: ...
print(double(3))
What Python prints
NotImplementedError: You should not call an overloaded function. A series of @overload-decorated functions outside a stub module should always be followed by an implementation that is not @overload-ed.
Why, and the fix
The stubs are only signatures. Add one definition without @overload, after the stubs, that handles every case: def double(value: int | str) -> int | str: return value * 2. mypy reports the missing implementation too: An overloaded function outside a stub file must have an implementation [no-overload-impl].
An implementation that skips a case
from typing import overload
@overload
def to_int(value: str) -> int: ...
@overload
def to_int(value: None) -> None: ...
def to_int(value: str | None) -> int | None:
return int(value)
print(to_int(None))
What Python prints
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
Why, and the fix
The overloads promise that to_int(None) returns None, but the implementation never checks. Narrow first: if value is None: return None, then return int(value). mypy catches this: it reports the return line with an [arg-type] error, because int() does not accept str | None.
A TypeIs function that returns False for some matches
from typing import TypeIs
def is_short(value: object) -> TypeIs[str]:
return isinstance(value, str) and len(value) < 5
def show(value: str | int) -> None:
if is_short(value):
print("short text", value)
else:
print(value + 1)
show(41)
show("a longer text")
What Python prints
TypeError: can only concatenate str (not "int") to str
Why, and the fix
mypy accepts value + 1, because TypeIs[str] says a False result means "not a str". is_short also returns False for long strings, so that promise is broken. Keep the predicate exact (return isinstance(value, str)) and test the length separately, or use a plain bool return, which narrows nothing.