Skip to content

Typing Review Checklist

A team can "use typing" and still have poor type quality. Hidden `Any`, meaningless aliases, confused validation boundaries, and over-abstracted protocols can create the illusion of safety without much real value. This chapter focuses on the review questions that matter.

Quick takeaway: good typing review is boundary review. The important questions are whether public signatures explain intent, whether `Any` is contained, whether protocols and concrete types are chosen intentionally, and whether runtime validation concerns are being confused with static typing.

A Typing Review Flow

Start with boundary clarity, not annotation count.

1. Are Public Signatures Descriptive?

  • Do parameter and return types describe the API from the caller's perspective?
  • Could dict[str, Any] become a TypedDict, DTO, or protocol?
  • Is the public API coupled too tightly to internal implementation types?

2. Does Any Leak Past the Boundary?

py
from typing import Any


def parse_payload(raw: dict[str, Any]) -> CreateUserCommand:
    ...

Some Any at raw-input boundaries is unavoidable. The important question is whether it gets constrained immediately or continues leaking into services, repositories, and domain logic.

3. Do Aliases Add Meaning?

Good aliases

  • add domain meaning
  • reduce repeated structural noise
  • improve API readability and reuse

Weak aliases

  • only shorten generic containers
  • wrap trivial one-off types and make code harder to read

4. Are Protocols and Concrete Types Chosen Intentionally?

  • Protocols are useful at extension points.
  • Concrete types are often clearer inside stable internal layers.
  • If everything becomes a protocol, the abstraction may be decorative rather than useful.

5. Are Validation and Typing Responsibilities Mixed?

  • typing describes a contract between callers and implementations
  • validation handles untrusted input at runtime
  • an annotation like str does not automatically make incoming JSON safe
  • good service boundaries validate first, then pass narrower types inward

Review Smells to Notice Quickly

SmellWhy it mattersTypical fix
Any everywhere in servicesstatic analysis becomes weakconstrain input with DTOs or TypedDict
frequent cast() callsthe type model and data flow disagreeadd predicates, TypeGuard, or better validation boundaries
too many protocolsabstraction leads the design instead of serving itkeep protocols only where substitution matters
request, response, and ORM types collapsedresponsibilities become hard to evolvesplit DTOs and entities
alias explosiontype reading slows downkeep only aliases with real semantic value

Review Checklist

Boundary first

Can you understand the external contract of the function or class from its types alone?

`Any` containment

Even if `Any` exists near raw input, is it constrained before it reaches deeper layers?

Abstraction discipline

Do protocols, generics, and aliases create real flexibility, or are they decorative complexity?

Runtime reality

Does the design still account for runtime validation and serialization instead of trusting annotations alone?

Good Supporting Examples

  • examples/py310_typing_and_zip_strict.py
  • examples/py312_type_params.py
  • examples/pydantic_validation_pipeline.py

Official References

Built with VitePress for a Python 3.14 handbook.