Why Type Hints Matter
Compare these two function signatures:Self-documenting code
Readers understand intent without reading the function body. Types serve as always-up-to-date documentation.
IDE superpowers
Your IDE provides accurate autocomplete, inline error detection, safe rename refactoring, and jump-to-definition — all driven by type information.
Tool integration
mypy catches type errors before you run your code. Pydantic reads your hints to validate and coerce data at runtime. FastAPI uses them to generate OpenAPI docs automatically.
Basic Variable Annotations
Function Annotations
Annotate every parameter and the return type. The return type goes after->.
Container Types
For collections, specify what they hold using square brackets (Python 3.9+):In Python 3.8 and earlier you had to import
List, Dict, Tuple, Set from typing and use uppercase: List[int], Dict[str, int]. Since Python 3.9, lowercase built-in types work directly. Use lowercase for all new code.Optional and Union Types
UseX | None (Python 3.10+) or Optional[X] (earlier versions) when a value might be absent:
Union Types (Multiple Allowed Types)
Literal Types — Restrict to Specific Values
UseLiteral when only a fixed set of values is valid:
The Any Type
Any opts a variable out of type checking — it accepts any type and is compatible with every other type. Use it sparingly as an escape hatch:
Type Aliases
Give a long or frequently reused type a short name:Static Type Checking with mypy
mypy reads your type hints and catches mismatches before you run your code:
mypy in your CI pipeline catches entire classes of bugs — passing the wrong argument type, returning the wrong shape from a function, calling a method that doesn’t exist on a type.