How to Merge TypedDicts in Python

Merge two TypedDict dictionaries with type-aware logic using NotRequired, **kwargs unpacking, and safe key updates.

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

Requires third-party packages — install first
pip install typing_extensions

Python code

27 lines
Python 3.11+
from typing import TypedDict, NotRequired, merge  # hypothetical

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

def merge_users(base: User, **overrides: User) -> User:
    """Merge two user dicts with typing-aware logic."""
    result: User = dict(base)
    for key, value in overrides.items():
        if value is not None:
            result[key] = value
    return result

def main() -> None:
    base_user: User = {"name": "Alice"}
    updates: User = {"email": "alice@example.com", "age": 30}
    
    merged = merge_users(base_user, **updates)
    print(f"Merged user: {merged}")

    explicit_merge = merge_users(base_user, name="Alice B.", age=31)
    print(f"Explicit merge: {explicit_merge}")

if __name__ == "__main__":
    main()

Output

stdout
Merged user: {'name': 'Alice', 'email': 'alice@example.com', 'age': 30}
Explicit merge: {'name': 'Alice B.', 'age': 31}

How it works

This pattern uses TypedDict to enforce dictionary shape at type-check time, catching typos like 'namr' before runtime. The NotRequired marker tells tools that email and age may be absent, so you can create partial user objects. The **overrides unpacking lets callers pass partial updates as keyword arguments, and the loop copies non-None values into a fresh dict, avoiding mutation of the original base. Using dict(base) creates a shallow copy so the original stays untouched. merge in typing is hypothetical; production code writes a small helper like this to keep merge logic explicit and typed.

Common mistakes

  • Mutating the base dict in place instead of copying with dict(base)
  • Forgetting to import NotRequired from typing_extensions on Python < 3.11
  • Allowing None values to overwrite existing keys
  • Assuming merge() exists in the stdlib typing module

Variations

  1. Use dict union operator: base | updates for simple merges without key filtering
  2. Use dataclasses with replace() when you need mutable objects instead of dicts

Real-world use cases

  • Patching a user profile in a web app when the client sends partial updates via a PATCH endpoint.
  • Merging configuration overrides from CLI flags, env vars, and a default config file at service startup.
  • Combining request context and authentication metadata from multiple middleware layers before passing to a handler.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Testing & modern typing

Related tutorials and quizzes for this topic.