Python Type Hints in Practice: From Hints to Strict Mypy
Python Type Hints in Practice: From Hints to Strict Mypy
Python type hints are no longer “nice to have”. With pyright running on every pull request and IDEs catching bugs as you type, the productivity delta is huge.
The minimum viable adoption
def total(items: list[float]) -> float:
return sum(items)
That single annotation gives you autocomplete, refactoring safety and a checkable contract.
The 80/20 toolkit
| Need | Use |
|---|---|
| Optional value | T | None (Python 3.10+) |
| Known dict shape | TypedDict |
| Structural typing | Protocol |
| Reusable generic | TypeVar, Generic[T] |
| Final / immutable | Final, Final[int] |
| Literal value | Literal["draft", "published"] |
| Assert refinement | TypeGuard / TypeIs (3.13+) |
TypedDict beats dict[str, Any]
class User(TypedDict):
id: int
email: str
is_admin: bool
def greet(u: User) -> str:
return f"hi {u['email']}"
You get autocomplete on keys and errors when a key is missing.
Protocols for duck typing
class SupportsClose(Protocol):
def close(self) -> None: ...
def cleanup(thing: SupportsClose) -> None:
thing.close()
No inheritance required — anything with a .close() method satisfies the protocol.
Strict mode incrementally
Move toward strict mypy without freezing development:
- Start with
--ignore-missing-imports. - Add
--strictper package via[tool.mypy.overrides]. - Use
# type: ignore[error-code]sparingly with the specific code. - Rate-limit new violations with a CI check on the diff only.
pyright vs mypy
- pyright — faster, strictest defaults, integrated into VS Code (Pylance).
- mypy — slower, plugin ecosystem (Django, SQLAlchemy), better for monorepos.
Many teams run both: pyright in the editor, mypy in CI.
TL;DR
Type hints in 2025 are how Python codebases scale past 50k lines. Start with public function signatures, adopt TypedDict and Protocol, then crank up strictness gradually.
Found this helpful? Try our free tools!
Explore Our Tools →