Interview frequency: …
Short answer
Use the union syntax X | Y and X | None (since Python 3.10), or Union and Optional from typing in older versions; Optional[X] means X | None and not "an optional parameter".
Explanation
The possibility of None should appear in the signature rather than hide behind Any, so the type checker forces you to handle it. After a check such as if user is None: return, the checker narrows the type automatically for the rest of the code. Note that a parameter having a default value does not make its type Optional; Optional is only about accepting None.
Code example
def find_user(user_id: int) -> User | None:
...
user = find_user(42)
print(user.name) # mypy: Item "None" has no attribute "name"
if user is not None:
print(user.name) # The type is now UserCommon mistakes
- Returning None from a function whose declared type is just User without updating the signature.
- Confusing an optional parameter (one with a default) with the Optional type.
Follow-up questions
- What is the difference between Any and object in type hints?
- What is the role of TypeVar and Generic in Python?