Skip to content

How to configure mypy strict mode

This guide assumes you have a Python project set up with uv and mypy installed as a dev dependency.

Running mypy with default settings is lenient. It skips function bodies that lack type annotations and ignores several categories of type errors. Strict mode closes these gaps by requiring annotations on all functions and enabling a curated set of optional checks. The exact flags included in --strict may change between mypy releases.

Enabling strict mode

Add the following to pyproject.toml:

[tool.mypy]
strict = true

Or pass the flag on the command line:

uv run mypy --strict src/

What strict mode enables

strict = true is shorthand for enabling these individual flags (as of mypy 1.x):

FlagWhat it does
disallow_untyped_defsRequires type annotations on every function definition
disallow_incomplete_defsRejects functions where only some arguments have annotations
disallow_untyped_callsFlags calls to functions that lack annotations
disallow_untyped_decoratorsErrors when an untyped decorator is applied to a typed function
disallow_any_genericsRequires explicit type parameters (e.g., list[int] instead of list)
disallow_subclassing_anyPrevents subclassing values of type Any
check_untyped_defsType-checks function bodies even without annotations
warn_return_anyWarns when a function returns a value typed as Any
warn_unused_configsWarns about unused [mypy-*] config sections (requires incremental = false to work)
warn_redundant_castsFlags unnecessary cast() calls
warn_unused_ignoresReports # type: ignore comments that suppress no errors
strict_equalityCatches comparisons between incompatible types
strict_bytesAvoids implicit str-to-bytes coercion in certain checks
no_implicit_reexportRequires explicit __all__ or re-import for public names
extra_checksEnables additional miscellaneous checks

Some optional checks like warn_unreachable are not included in --strict. Check the mypy command-line docs for the current list.

Adopting strict mode in an existing codebase

Turning on strict = true in a large existing project usually produces hundreds of errors. A gradual approach works better.

Start with a subset of flags

Instead of enabling everything at once, pick the most impactful flags and add them one at a time:

[tool.mypy]
check_untyped_defs = true
disallow_incomplete_defs = true
warn_redundant_casts = true
warn_unused_ignores = true
strict_equality = true

Fix the errors from these, then add more flags until the full set is covered.

Use per-module overrides

Rather than enabling strict mode globally, apply stricter checks only to modules that are already well-typed:

[tool.mypy]
check_untyped_defs = true

[[tool.mypy.overrides]]
module = ["mypackage.api", "mypackage.api.*"]
strict = true

This enforces strict checking on modules that are ready for it while keeping the rest of the codebase under lighter rules. As you annotate more modules, add them to the override list or move to global strict mode.

Start strict and subtract

For new projects (or projects close to full coverage), enable strict mode and selectively disable flags that cause too much friction:

[tool.mypy]
strict = true
warn_return_any = false

Handling third-party libraries without type stubs

mypy may report import errors for third-party packages that lack type annotations, stubs, or a py.typed marker. This is standard mypy behavior, not specific to strict mode. Silence these per-package:

[[tool.mypy.overrides]]
module = ["some_untyped_library", "some_untyped_library.*"]
ignore_missing_imports = true

Check typeshed and PyPI for stub packages before suppressing. Many popular libraries have stubs available as separate packages (e.g., types-requests, types-PyYAML). Install them as dev dependencies:

uv add --dev types-requests types-PyYAML

Running mypy with uv

Add mypy as a dev dependency if it is not already present:

uv add --dev mypy

Then run it:

uv run mypy src/

Related resources

Last updated on

Please submit corrections and feedback...