# mypy: Python Static Type Checker


mypy is a static type checker for Python that analyzes type annotations to detect bugs before runtime. It has been the default Python type checker since 2012 and has the broadest ecosystem support of any Python type checking tool.

## When to use mypy

Use mypy when you want to catch type-related bugs before runtime by adding static type checking to a Python project. It is the most established Python type checker with broad ecosystem support, making it a reliable default for projects that are adopting type annotations incrementally. For faster checking or tighter VS Code integration, consider [pyright](https://pydevtools.com/handbook/reference/pyright.md); for an emerging alternative from the creators of [Ruff](https://pydevtools.com/handbook/reference/ruff.md), see [ty](https://pydevtools.com/handbook/reference/ty.md).

## Key Features

- Gradual typing: add type annotations incrementally to an existing codebase. Unannotated functions are skipped by default unless `--check-untyped-defs` or `--strict` is enabled.
- Type inference: deduces types from assignments, return values, and usage patterns when explicit annotations are absent.
- Generic types, unions, protocols: supports parameterized types (`list[int]`), union types (`str | int`), structural subtyping via `Protocol`, and `TypedDict` for typed dictionaries.
- Type stubs: works with typeshed and custom stub files for libraries that don't ship inline annotations.
- mypyc compilation: mypy includes mypyc, a compiler that translates type-annotated Python into C extensions for significant runtime speedups.

## Recent Developments

### mypy 2.0 (May 2026)

mypy 2.0 ships parallel type checking and flips several flag defaults that change inference behavior. The release lands the work tracked for years in [issue #933](https://github.com/python/mypy/issues/933).

- Parallel checking (experimental): pass `--num-workers N` or `-nN` to type-check across `N` worker processes. The release notes report **gains of up to 5x with 8 workers**, with the disclaimer that the speedup depends on a project's import structure and the host environment. Parallel mode implicitly enables the native parser and still has minor semantic differences from single-process mode that future releases will close.
- `--local-partial-types` is now default, which changes how mypy infers types from assignments in other scopes. Code that passed under 1.x can surface new errors after upgrade.
- `--strict-bytes` is now default per [PEP 688](https://peps.python.org/pep-0688/): `bytearray` and `memoryview` values are no longer assignable to the `bytes` type.
- `--allow-redefinition` semantics changed. The flag now behaves like `--allow-redefinition-new` did in 1.20, requires `--local-partial-types` (which is now default), and forbids two type annotations on the same variable. Pass `--allow-redefinition-old` to keep the legacy behavior.
- `--python-version 3.9` is rejected with an error. The minimum target is now 3.10.
- `--ignore-missing-imports` is now consistent across all packages; the legacy bundled-stub special case is gone.

### mypy 1.18 through 1.20 (March 2026)

- Performance: versions 1.18+ delivered roughly 40% faster type checking compared to 1.17, with some cases improving by 10x. A binary cache format and SQLite-backed cache (both now enabled by default) make incremental builds faster.
- Native parser: an experimental parser based on [Ruff](https://pydevtools.com/handbook/reference/ruff.md)'s parser became available via `uv add --dev "mypy[native-parser]"` and the `--native-parser` flag.
- Python 3.14 support: mypy handles t-strings ([PEP 750](https://peps.python.org/pep-0750/)) and ships mypyc-accelerated wheels for Python 3.14 free-threading builds.
- Better type narrowing: mypy 1.20 reworked narrowing for equality expressions, containment checks, and match statements to be more aggressive and more correct.

> [!NOTE]
> mypy 2.0 rejects `--python-version 3.9`. mypy 1.20 had already dropped runtime support for Python 3.9 itself; 2.0 also drops it as a target.

## Pros

- Most established type checker with the broadest library compatibility and community resources
- Gradual adoption path via per-module configuration overrides
- mypyc compiler can speed up runtime performance of type-annotated code
- Recent versions have closed the performance gap with newer tools

## Cons

- Skips unannotated functions by default, which surprises users who expect it to catch obvious errors everywhere
- No built-in language server; editor integration relies on third-party plugins or pairing with [pyright](https://pydevtools.com/handbook/reference/pyright.md) or [ty](https://pydevtools.com/handbook/reference/ty.md)
- Slower than [ty](https://pydevtools.com/handbook/reference/ty.md) on large codebases, though roughly on par with [pyright](https://pydevtools.com/handbook/reference/pyright.md) on current versions
- Struggles with highly dynamic Python patterns

## Installation and Usage

```bash
# Add as a dev dependency
uv add --dev mypy

# Check a single file
uv run mypy example.py

# Check multiple files or directories
uv run mypy src/ tests/

# Enable stricter checking
uv run mypy --strict example.py

# Type-check in parallel (mypy 2.0+)
uv run mypy -n 8 src/
```

## Configuration

mypy reads configuration from `mypy.ini`, `.mypy.ini`, `setup.cfg`, or `pyproject.toml` (under `[tool.mypy]`). Per-module overrides let you treat vendored code or test files differently from application code:

```toml {filename="pyproject.toml"}
[tool.mypy]
python_version = "3.12"
strict = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
```

## Learn More

- [How do mypy, pyright, and ty compare?](https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare.md)
- [How to configure mypy strict mode](https://pydevtools.com/handbook/how-to/how-to-configure-mypy-strict-mode.md)
- [How to configure mypy and django-stubs in a uv project](https://pydevtools.com/handbook/how-to/how-to-configure-mypy-and-django-stubs-in-a-uv-project.md)
- [How to gradually adopt type checking in an existing Python project](https://pydevtools.com/handbook/how-to/how-to-gradually-adopt-type-checking-in-an-existing-python-project.md)
- [How to configure Claude Code with a Python type checker](https://pydevtools.com/handbook/how-to/how-to-configure-claude-code-with-a-python-type-checker.md)
- [How to migrate from mypy to ty](https://pydevtools.com/handbook/how-to/how-to-migrate-from-mypy-to-ty.md)
- [How to try the ty type checker](https://pydevtools.com/handbook/how-to/how-to-try-the-ty-type-checker.md)
- [ty](https://pydevtools.com/handbook/reference/ty.md) reference
- [pyright](https://pydevtools.com/handbook/reference/pyright.md) reference
- [mypy 2.0 picks parallelism over a rewrite](https://pydevtools.com/blog/mypy-2-0-parallel-type-checking.md) walks through the 2.0 release and how the parallel-checking gains compare to the Rust-based type checkers
- [Official mypy Documentation](https://mypy.readthedocs.io/)
- [mypy GitHub Repository](https://github.com/python/mypy)
- [Mypy 2.0 Release Blog Post](https://mypy-lang.blogspot.com/2026/05/mypy-20-relased.html)
- [Mypy Changelog](https://mypy.readthedocs.io/en/stable/changelog.html)
