The handful of times I’ve reached for typing.TypeGuard in Python, I’ve always been
confused by its behavior and ended up ditching it with a # type: ignore comment.
For the uninitiated, TypeGuard allows you to apply custom type narrowing. For example,
let’s say you have a function named pretty_print that accepts a few different types and
prints them differently onto the console:
from typing import assert_never
def pretty_print(val: int | float | str) -> None:
if isinstance(val, int): # assert_type(val, int)
print(f"Integer: {val}")
elif isinstance(val, float): # assert_type(val, float)
print(f"Float: {val}")
elif isinstance(val, str): # assert_type(val, str)
print(f"String: {val}")
else:
assert_never(val)
If you run it through mypy, in each branch, the type checker automatically narrows the
type and knows exactly what the type of val is. You can test the narrowed type in each
branch with the typing.assert_type function.