Alex Lin Wang 王帅

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!