TypedDict tells your type checker what keys to expect, but it does NOT enforce those keys at runtime. A TypedDict that should have name can still be missing it, and accessing user['name'] raises KeyError exactly like a regular dict.

The minimal reproducer
from typing import TypedDict
class User(TypedDict):
name: str
age: int
user: User = {'age': 30} # mypy warns but runtime is fine
print(user['name']) # KeyError: 'name'
Pattern 1: Required vs NotRequired (Python 3.11+)
from typing import TypedDict, NotRequired
class User(TypedDict):
name: str # required by default
age: NotRequired[int] # optional, mypy understands
user: User = {'name': 'Alice'} # OK, age can be missing
age = user.get('age', 0) # safe, KeyError-free
Pattern 2: total=False for fully optional dicts
class Config(TypedDict, total=False):
host: str
port: int
cfg: Config = {} # all keys optional
host = cfg.get('host', 'localhost')
Pattern 3: Switch to dataclasses for runtime enforcement
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int = 0
# This raises TypeError at construction if name is missing
user = User(age=30) # TypeError: missing 1 required argument: 'name'
Dataclasses (and Pydantic models) check field presence at construction time, so missing required fields fail early instead of deep inside your code.
Frequently Asked Questions
Does TypedDict raise an error at runtime if a required key is missing?
No. TypedDict is a type hint only. Missing required keys at runtime behave exactly like a regular dict and raise KeyError on bracket access. mypy and pyright catch this statically before runtime.
When was NotRequired added to TypedDict?
Python 3.11 (PEP 655). For earlier Python, use total=False to make every key optional, or split into two classes (RequiredFields and AllFields with inheritance).
Should I use TypedDict or Pydantic BaseModel?
TypedDict for zero-overhead type hints on existing dict data (no runtime cost). Pydantic for full runtime validation, JSON parsing, and serialization. TypedDict is faster, Pydantic is safer.
Can I check at runtime if a TypedDict has all required keys?
Use typing.get_type_hints(MyTypedDict).keys() then check membership: required = set(MyTypedDict.__required_keys__); if not required.issubset(data): raise ValueError. Available from Python 3.9+.
Does TypedDict work with JSON loading?
Yes, just annotate: data: MyType = json.loads(text). The annotation is for the type checker only; json.loads still returns a regular dict. For runtime validation of JSON, use Pydantic or msgspec.
