Understand the contract
TypedDict describes a dictionary shape to a type checker: particular string keys correspond to particular value types. It is useful for records from JSON-like data where a generic dict[str, object] loses the relationship between each key and its value.
Import TypedDict from typing, then declare fields in a class body. Instances are ordinary dictionaries at runtime. TypedDict does not create attribute access, validate received JSON, or make keys immutable.
Follow the runtime behavior
Fields are required by default. NotRequired marks a field that may be absent, which differs from a required field whose value may be None. total=False makes fields declared in that definition optional; Required can mark an individual exception.
Use dictionary membership or get before accessing an optional field. Do not use isinstance(value, YourTypedDict): TypedDict classes do not support runtime instance checks. Validate external data explicitly before treating it as a trusted record.
Apply it and practise
Choose TypedDict for existing dictionary-shaped interfaces, and a dataclass or ordinary class when methods and runtime object identity are useful. Type annotations still do not enforce runtime types.
Exercise: define Product with required name and price fields and an optional discount field. Write a function that applies the discount only when present. Test records with and without it; then explain why a string price needs separate validation.
Syntax
class Movie(TypedDict):
title: str
year: intExamples
Describe a record
Use named keys when passing a small structured record between functions.
from typing import TypedDict
class Movie(TypedDict):
title: str
year: int
movie: Movie = {"title": "Arrival", "year": 2016}
print(movie["title"])
print(type(movie).__name__)- The declaration assigns types to two named keys. Subscription retrieves the title, and type reveals that the record is still a normal dict.
- Use named keys when passing a small structured record between functions.
- The annotation does not reject missing keys or wrong values at runtime; no validator has run.
- Expected output: Arrival dict
Read an optional field
Use this pattern for a display preference that can be omitted.
from typing import NotRequired, TypedDict
class Profile(TypedDict):
name: str
nickname: NotRequired[str]
def display(profile: Profile) -> str:
return profile.get("nickname", profile["name"])
print(display({"name": "Ada"}))
print(display({"name": "Ada", "nickname": "A"}))- NotRequired allows nickname to be absent in the static contract. get returns the nickname if present and otherwise uses the required name.
- Use this pattern for a display preference that can be omitted.
- An explicitly stored empty nickname is still present. Optional presence does not mean that None is a valid value.
- Expected output: Ada A
Require one configuration key
Use this shape for a configuration record with one mandatory destination and optional tuning.
from typing import Required, TypedDict
class Settings(TypedDict, total=False):
host: Required[str]
retries: int
settings: Settings = {"host": "localhost"}
print(settings["host"])
print(settings.get("retries", 3))- total=False makes retries optional while Required restores the requirement for host. get supplies an application default without inserting it into the dictionary.
- Use this shape for a configuration record with one mandatory destination and optional tuning.
- Required is a static requirement. Constructing an empty dictionary would still succeed at runtime.
- Expected output: localhost 3
Best practices
- Use dictionary membership or get before accessing an optional field. Do not use isinstance(value, YourTypedDict): TypedDict classes do not support runtime instance checks. Validate external data explicitly before treating it as a trusted record.
- Choose TypedDict for existing dictionary-shaped interfaces, and a dataclass or ordinary class when methods and runtime object identity are useful. Type annotations still do not enforce runtime types.
Runtime & versions
Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Python language reference