Type Hints Basics
9 examples to get you started with Python type hints - 6 basic and 3 intermediate.
Search across all documentation pages
9 examples to get you started with Python type hints - 6 basic and 3 intermediate.
uv add --dev mypy).Document expected types on names and signatures.
name: str = "Ada"
count: int = 0
def greet(user: str) -> str:
return f"Hello, {user}"__annotations__ but not enforced at runtime.-> None documents no useful return value.Related: Built-in & Collection Generics - list[int], dict[str, int]
Use built-in generics for containers (3.9+).
users: list[str] = []
index: dict[str, int] = {}
unique: set[int] = set()list without params means untyped list to strict checkers.tuple[int, str].Related: Built-in & Collection Generics - Sequence, Mapping
Nullable values use union with None.
def find_user(user_id: int) -> dict | None:
return None
email: str | None = NoneOptional[str] equivalent to str | None (older style).if x is not None before use - checkers refine types.Optional when None is not allowed.Related: Optional, Union & the | Operator - narrowing
Check types statically in CI.
uv run mypy src/# pyproject.toml snippet
[tool.mypy]
python_version = "3.14"
strict = false
warn_return_any = truestrict = true overrides.pyproject.toml [tool.mypy] section.Related: mypy & pyright Setup - full config
Combine runtime checks with static narrowing.
def handle(value: str | int) -> str:
if isinstance(value, str):
return value.upper()
return str(value * 2)isinstance helps mypy/pyright narrow unions.match/case also narrows when patterns type-specific.Related: Optional, Union & the | Operator - type guards
Any opts out of checking - use sparingly.
from typing import Any
def legacy_bridge(payload: Any) -> dict[str, Any]:
assert isinstance(payload, dict)
return payloadAny is contagious - returns infect callers.object when any value allowed but not arbitrary operations.Any at system edges over time.Type higher-order functions.
from collections.abc import Callable
def apply(fn: Callable[[int, int], int], a: int, b: int) -> int:
return fn(a, b)Callable[[ArgTypes], ReturnType] documents function shape.ParamSpec preserves decorator signatures (advanced).Callable over untyped functions in public APIs.Related: Overloads & Callable Types - ParamSpec
Annotate instance and class variables.
class Counter:
total: int = 0
def __init__(self) -> None:
self.value: int = 0__init__.ClassVar marks attributes not overridden on instances.Related: dataclasses - typed fields
Add types module by module.
# mypackage/service.py (typed)
def compute(x: int) -> int:
return x + 1
# mypackage/legacy.py (untyped for now)
def legacy(): ...check_untyped_defs after baseline coverage.# type: ignore[code] sparingly with comment why.Related: Gradual Typing Strategy - rollout plan
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 16, 2026