TypedDict
September 6, 2025 • 5 min read
TypedDict for type-safe dictionaries with optional keys when working with
API responses and external data.
When you return a JSON from a REST API call, sometimes, modeling that API
response is difficult. A normal python dictionary is structured as dict[str, Any] which may be too many degrees of freedom for some people. However, a dataclass
is only suitable for internal data representations with fixed structures, but
if you're using external, raw/untrusted data, you need less explicit structures.
# Example function
def process_user(data: dict) -> None:
# we expect: {\"id\": int, \"email\": str (optional)}
print(f"User id = {data['id']}")
if "email" in data:
print(f"Email = {data['email']}")
For this case, instead of a dictionary or dataclass, the TypedDict would allow you to define a dictionary with specific keys and value types
which allow you to specify both required and optional keys, which allow for
stronger type checking during development.
from typing import TypedDict, NotRequired
class UserDict(TypedDict):
id: int
email: NotRequired[str] # now optional
def process_user(data: UserDict) -> None:
print(f"User id = {data['id']}")
if "email" in data:
print(f"Email = {data['email']}")
process_user({\"id\": 42}) # ✅ ok, email optional
process_user({\"id\": 42, \"email\": \"alex@example.com\"}) # ✅ ok
process_user({\"email\": \"oops\"}) # ❌ type checker error: missing "id"
Advantages of TypedDict
- Flexible Structure: Better than
dict[str, Any]but more flexible than dataclasses - API Modeling: Perfect for modeling JSON responses from REST APIs
- Optional Keys: Support for both required and optional
fields with
NotRequired - Static Type Safety: Get compile-time type checking for dictionary access
- External Data: Ideal for working with external, raw, or untrusted data sources
Questions or feedback? Feel free to reach out!