On this page
The core idea
Python's type hints are annotations that tools read; the interpreter does not enforce them at runtime. A static type checker such as mypy or Pyright reads the hints and reports places where values of the wrong type may flow, such as passing None where a string is required or misspelling a dictionary key. The highest value comes from annotating boundaries: function parameters and return values, class attributes and the shapes of structured data. Inside functions, the checker usually infers local types.
A practical approach
Step 1
Annotate the signatures of public functions first: parameter types and return types, including Optional or X | None where None is possible.
Step 2
Replace loose dictionaries with typed structures, such as dataclasses or TypedDict, for data passed between functions.
Step 3
Run a type checker in your editor and in continuous integration so issues appear while code is written.
Step 4
Turn on stricter options gradually, module by module, rather than all at once on a large codebase.
Step 5
Validate external input at runtime separately; type hints describe what you expect, not what arrives from a file or API.
Worked example
A function get_learner(email) returns a Learner or None when no learner exists. Several callers immediately read learner.name. Annotating the return type as Learner | None makes the type checker flag every one of those callers, revealing three code paths that would have crashed for unknown email addresses. Each caller now handles the missing case explicitly.
A mistake to avoid
Do not silence the checker with Any or # type: ignore whenever it complains. Each suppression hides a possible bug; leave a comment explaining why it is safe when you genuinely need one.
Try it yourself
Choose one module in a Python project, add type hints to its function signatures and replace one dictionary with a dataclass. Run mypy or Pyright and fix or document every reported issue.
Your implementation checklist
- Public functions have parameter and return annotations
- None is represented explicitly where it is possible
- Structured data uses dataclasses or TypedDict
- A type checker runs in the editor and CI
- Suppressions are rare and explained
Share or cite this guide
Innovate with Ajay Editorial (2026-10-07). Add Python Type Hints Where Bugs Cross Function Boundaries. https://innovatewithajay.com/blogs/add-python-type-hints-at-boundaries
