Static type checking helps to catch bugs earlier and contributes to the long-term maintainability and overall quality of Python codebases. This post explains why we chose mypy as our static type checker over other alternatives.
Context and problem statement
We already use type hints extensively in all our Python codebases to document intent, improve readability, and support richer IDE feedback. However, without a mechanism to enforce these annotations, they remain just guidelines, which can easily drift out of sync with the actual behaviour of the code. The goal of static type checkers is to verify that there are no inconsistencies between declared types and actual usage by analysing the code without executing it. Static type checking can be integrated both in local development workflows and CI/CD pipelines, effectively preventing type errors from entering the codebase.
Given that there are multiple static type checkers available for Python, the question then is:
Which static type checking tool should we adopt to enforce our existing type hints consistently across development and CI?
Decision drivers
The static type checker should:
- Enforce existing type hints.
- Integrate well with IDEs (particularly VS Code). Additional features like inline feedback and autocompletion are a bonus.
- Integrate with existing GitHub CI pipelines.
- Handle both typed and untyped dependencies.
- Run fast enough for frequent checks during local development.
- Be actively maintained, widely adopted, and well documented.
- Improve the maintainability of our Python projects.
Considered options
The most popular static type checkers available for Python are:
Mypy
mypy is the oldest and most widely used static type checker. It is written in Python and developed by the Python community.
Pyright
Pyright is a fast static type checker for Python developed by Microsoft. It powers VS Code’s Pylance extension and can also run as a standalone CLI tool.
Pyre and Pyrefly
Pyre is a static type checker developed by Facebook/Meta. It focuses on speed and incremental checking, ideal for large codebases. Pyrefly is Meta’s next-generation type checker for Python, written in Rust.
Ty
ty is an extremely fast type checker for Python, written in Rust by the creators of uv and Ruff.
Benefits
- Very fast, probably the fastest of all alternatives.
- Most common IDEs are supported.
- Can be integrated into CI pipelines.
- Comes with a language server offering code navigation, autocompletion, auto-import, and more.
- Supports advanced typing features in modern Python.
- Configurable.
- We already use Ruff and
uv, so staying in the same ecosystem for type checking is an attractive prospect.
Decision outcome
We decided on mypy because it is the de-facto standard for Python type checking, has excellent documentation and community support, is easy to set up, and runs both as a CLI tool and via the VS Code extension with consistent output. Its drawback, slower performance on very large codebases, is less relevant for us because our repositories are small compared to giants like Facebook. Additionally, we continue to use VS Code’s Pylance language server, which runs Pyright internally, complementing the feedback we get from mypy.
Consequences
- We should keep an eye on
mypy’s performance, just in case it begins to impact developer experience negatively. - Given our use of other tools by Astral, we have a good case for switching to
tyonce it becomes stable.