mypy
mypy copied to clipboard
Type narrowed to `Never` when using `TypeIs` with union of callables
from typing import Any, Callable
from typing_extensions import TypeIs, assert_type, assert_never
def is_single_callable(c: Callable[[], Any] | Callable[[int], Any]) -> TypeIs[Callable[[int], Any]]:
...
def test(c: Callable[[], Any] | Callable[[int], Any]):
if is_single_callable(c):
reveal_type(c)
else:
# mypy thinks this is unreachable
a: int = 1
While c could be narrowed to Callable[[], Any] in the else block, it is currently narrowed to Never. For reference, see this discussion.
Your Environment
- Mypy version used: 1.12.1
- Mypy command-line flags:
--warn-unreachable - Python version used: 3.12
It turns out this affects any union of a generic type (not just Callable). For example:
def is_int_list(c: list[str] | list[int]) -> TypeIs[list[int]]:
...
def foo(x: list[str] | list[int]) -> None:
if is_int_list(x):
reveal_type(x) # N: Revealed type is "builtins.list[builtins.int]"
else:
reveal_type(x) # E: Statement is unreachable
reveal_type(x) # N: Revealed type is "builtins.list[builtins.int]"