Python - Typing Advanced

Overview

Estimated time: 30–45 minutes

Go beyond basics with structural typing (Protocols), precise dict types (TypedDict), generics, and callable signatures.

Learning Objectives

  • Define Protocols and use runtime_checkable where useful.
  • Use TypedDict for structured dicts; migrate gradually.
  • Write generic classes/functions with TypeVar/ParamSpec.

Examples

from typing import Protocol, runtime_checkable, TypedDict, TypeVar, Generic, Callable, ParamSpec

@runtime_checkable
class SupportsClose(Protocol):
    def close(self) -> None: ...

class User(TypedDict):
    id: int
    name: str

T = TypeVar('T')
P = ParamSpec('P')

def make_cached(fn: Callable[P, T]) -> Callable[P, T]:
    cache = {}
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
        key = (args, tuple(sorted(kwargs.items())))
        if key not in cache:
            cache[key] = fn(*args, **kwargs)
        return cache[key]
    return wrapper

Guidance & Patterns

  • Prefer Protocols over concrete ABCs when only behavior matters.
  • Use TypedDict gradually; keep runtime code simple.

Best Practices

  • Adopt typing incrementally; enable strictness in CI over time.
  • Document public APIs with clear types; avoid over-typing internals.

Exercises

  1. Define a protocol for a cache and implement two backends; check with mypy/pyright.
  2. Write a generic function with TypeVar that preserves input type.