How to Use TypedDict and Dataclasses in Python

Create typed data structures with TypedDict and dataclasses, then use them as helper functions for describing objects in a type-safe way.

Easy Python 3.11+ Aug 9, 2026 Testing & modern typing 12 views 0 copies

Python code

33 lines
Python 3.11+
from typing import TypedDict, NotRequired, Optional
from dataclasses import dataclass


class User(TypedDict):
    name: str
    age: NotRequired[int]
    email: Optional[str]


@dataclass
class Product:
    id: int
    title: str
    price: float = 0.0


def describe_user(user: User) -> str:
    age = user.get("age", "unknown")
    email = user.get("email", "not provided")
    return f"{user['name']} (age: {age}, email: {email})"


def describe_product(product: Product) -> str:
    return f"Product #{product.id}: {product.title} — ${product.price:.2f}"


if __name__ == "__main__":
    sample_user: User = {"name": "Alice", "email": None}
    sample_product = Product(id=101, title="Keyboard", price=49.99)

    print(describe_user(sample_user))
    print(describe_product(sample_product))

Output

stdout
Alice (age: unknown, email: not provided)
Product #101: Keyboard — $49.99

How it works

TypedDict defines a dictionary schema with optional keys (NotRequired) and nullable fields (Optional), enabling type checking on dict-like structures. The dataclass decorator auto-generates __init__, __repr__, and equality methods, reducing boilerplate for class-based data. Helper functions like describe_user and describe_product provide single-responsibility formatting, leveraging type hints for better IDE support and static analysis. Optional[str] means the value can be None or a string, while get() with defaults makes handling missing keys safe at runtime.

Common mistakes

  • Using `Optional[int]` instead of `NotRequired[int]` when the key may be absent entirely
  • Forgetting that `TypedDict` is checked statically, not at runtime — invalid keys won't raise errors
  • Omitting `from __future__ import annotations` when mixing dataclasses and TypedDicts in older Python versions

Variations

  1. Use `typing.Protocol` for structural subtyping instead of `TypedDict`
  2. Define dataclass fields with `field(default_factory=...)` for mutable defaults

Real-world use cases

  • Typing API payloads in a client library so endpoint responses are validated by the type checker.
  • Defining immutable config objects with dataclasses and defaults for application settings.
  • Building helper formatters that display user or product data consistently across a web UI.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Testing & modern typing

Related tutorials and quizzes for this topic.