You write a helper that raises a validation error, so each check is one line.
Then mypy rejects code that looks correct. Save this as checks.py:
class ValidationError(ValueError):
pass
def fail(message: str) -> None:
raise ValidationError(message)
def require_text(value: object) -> str:
if not isinstance(value, str):
fail("expected a string")
return value
$ mypy --strict checks.py
checks.py:12: error: Incompatible return value type (got "object", expected "str") [return-value]
Found 1 error in 1 file (checked 1 source file)
-> None tells mypy that fail can return normally. So mypy assumes that a
value that is not a string can reach return value.
Annotate the helper with Never
Never is the return type of a function that never returns normally. It
always raises, exits the program, or loops forever.
from typing import Never
class ValidationError(ValueError):
pass
def fail(message: str) -> Never:
raise ValidationError(message)
def require_text(value: object) -> str:
if not isinstance(value, str):
fail("expected a string")
return value
assert require_text("ready") == "ready"
Now mypy knows that nothing after fail(...) runs. So at return value,
value must be a str, and the error goes away.
The annotation is for the type checker only. Python does not check it when
the code runs, so write a test that checks that fail raises.
NoReturn, also in typing, means the same as Never. Older code uses
NoReturn, and Never arrived in Python 3.11. Pick one and use it across your
project.
Use Never on a method that always raises
Return Errors as Values with a Result Type, at the end of this track, has two
classes. Ok.unwrap() returns the stored value, and Err.unwrap() always
raises. Annotate Err.unwrap() with -> Never. Then unwrap() on a result
that might be either one has exactly the value's type. With -> None instead,
every caller would have to handle a None that never comes.
Going further
assert_never uses Never to check that a match statement or an if chain
handles every case.
The assert_never exercise in the type hints track
lets you practice it.