TypedDict & NamedTuple
TypedDict adds static shape to dicts - perfect for JSON blobs. NamedTuple provides immutable records lighter than dataclasses for read-only rows.
Search across all documentation pages
TypedDict adds static shape to dicts - perfect for JSON blobs. NamedTuple provides immutable records lighter than dataclasses for read-only rows.
from typing import TypedDict
class UserRow(TypedDict):
id: int
email: str
def load(row: UserRow) -> str:
return row["email"]When to reach for this:
response.json() structuresfrom typing import NamedTuple, NotRequired, TypedDict
class Address(TypedDict, total=False):
street: str
city: str
zip: NotRequired[str]
class User(TypedDict):
id: int
name: str
address: Address
class Point(NamedTuple):
x: int
y: int
def format_user(user: User) -> str:
city = user.get("address", {}).get("city", "unknown")
return f"{user['name']} ({city})"
def distance(a: Point, b: Point) -> float:
return ((a.x - b.x) ** 2 + (a.y - b.y) ** 2) ** 0.5
if __name__ == "__main__":
row: User = {"id": 1, "name": "Ada", "address": {"city": "London"}}
print(format_user(row))
print(distance(Point(0, 0), Point(3, 4)))What this demonstrates:
total=False makes Address keys optional staticallyNotRequired marks optional keys in otherwise total TypedDict (3.11+)user["name"] accesstotal=True (default).| Type | Runtime | Mutable |
|---|---|---|
| TypedDict | dict | Yes |
| NamedTuple | tuple | No |
| dataclass | object | Configurable |
| Pydantic | BaseModel | Yes |
# Required key in partial TypedDict (3.11+)
class Config(TypedDict, total=False):
debug: NotRequired[bool]
host: str # required if using Required[] in partial patternsuser["emial"]; runtime still KeyError. Fix: Static check + tests.| Alternative | Use When | Don't Use When |
|---|---|---|
| Pydantic BaseModel | HTTP validation | Hot loop dict access |
| dataclass | Methods + defaults | Must remain dict |
| attrs | attrs ecosystem | Stdlib minimal |
| plain dict[str, Any] | Prototype only | Production API |
TypedDict when value must stay dict (JSON APIs). dataclass for domain objects with behavior.
NamedTuple lighter tuple semantics; frozen dataclass when defaults and methods needed.
total=False on whole dict or NotRequired per key in 3.11+.
Compose smaller TypedDicts as field types - mirrors JSON nesting.
Manual mapping or Pydantic model_validate bridging layers.
Annotate in class body - NamedTuple supports PEP 526 annotations.
No runtime type - isinstance checks dict only. Use validation library.
Cast rows to TypedDict after validating required keys present.
Child can add optional keys; understand required key rules across inheritance.
Pydantic preferred for OpenAPI; TypedDict for internal service dict contracts.
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