Python
26 / 29
Python Typing
Make Python feel like a statically-typed language — catch bugs before they ship.
Why bother?
Type hints don't affect runtime speed, but they catch entire classes of bugs in CI, power autocomplete, and make refactors safe. Every serious codebase uses them.
1. The Basics
def greet(name: str, times: int = 1) -> str:
return ("Hello, " + name + "!\n") * times
ages: dict[str, int] = {"alice": 30}
scores: list[float] = [0.91, 0.88]
maybe_user: str | None = None # PEP 604 union (3.10+)2. Generics
Write functions and containers that preserve the input type. Python 3.12+ uses the clean[T] syntax.
def first[T](items: list[T]) -> T | None:
return items[0] if items else None
x: int = first([1, 2, 3]) # inferred as int
y: str | None = first(["a", "b"]) # inferred as str | None
class Cache[K, V]:
def __init__(self) -> None:
self._data: dict[K, V] = {}
def get(self, key: K) -> V | None:
return self._data.get(key)3. Protocols (Structural Typing)
A Protocol defines a shape. Anything with the right methods satisfies it — no inheritance required. This is Python's version of Go interfaces.
from typing import Protocol
class Estimator(Protocol):
def fit(self, X, y) -> None: ...
def predict(self, X) -> list: ...
def cross_val(model: Estimator, X, y) -> float:
model.fit(X, y)
return score(model.predict(X), y)
# Works with sklearn, xgboost, your custom class — anything with .fit/.predict4. TypedDict & Literal
from typing import TypedDict, Literal
class User(TypedDict):
id: int
name: str
role: Literal["admin", "member", "guest"]
def grant(u: User, perm: Literal["read", "write"]) -> None: ...5. Useful Tools
Optional[X]=X | NoneCallable[[int, str], bool]— function signaturesFinal,ClassVar— immutability markersNewType("UserId", int)— distinct types from primitivescast(T, x)— escape hatch when the checker can't infer
6. Static Checking in CI
# pyproject.toml
[tool.mypy]
strict = true
python_version = "3.12"
# CI step
$ mypy src/ # fails the build on type errors
$ pyright src/ # Microsoft's faster alternativePragmatic rules
Type all public functions. Use
Any sparingly and only at boundaries. Prefer Protocols over abstract base classes for new code. Enable strictmode from day one — it's painful to retrofit.