ty: A Complete Guide to Python's Fastest Type Checker
ty is a Python type checker and language server built by Astral, the team behind Ruff and uv. Written in Rust, it checks Python code for type errors an order of magnitude faster than mypy. The same binary that runs ty check in CI also serves as a full language server, powering editor features like completions and go-to-definition.
Why ty exists
Python has had type checkers for over a decade. mypy, the original, is written in Python (with an optional C extension) and remains the most widely used. pyright, written in TypeScript, brought faster performance and tighter editor integration through Pylance for VS Code. Both tools work, but each carries trade-offs that compound at scale.
mypy is slow on large codebases. It skips unannotated functions by default, which means partially-typed projects get incomplete coverage unless you opt in with --check-untyped-defs. It has no built-in language server, so editor integration depends on third-party LSP wrappers. pyright is faster, but it requires Node.js. Its best editor experience lives in Pylance, a closed-source VS Code extension that bundles pyright with additional features.
ty was designed to sidestep these trade-offs. A single Rust binary provides both a CLI type checker and a full Language Server Protocol implementation with no runtime dependencies. There is no separate language server to install, no Node.js runtime, and no gap between what runs in your editor and what runs in CI.
ty also introduces a gradual guarantee: adding type annotations to your code will never introduce new errors. You can annotate a function’s return type and ty won’t flag callers that were already passing the wrong type just because the annotation appeared. Each annotation only narrows down existing errors rather than creating new ones. The guarantee makes incremental adoption practical for large codebases.
For a detailed feature-by-feature breakdown, see How do mypy, pyright, and ty compare?.
When to use ty
New projects using uv and Ruff: ty completes the Astral toolchain. All three tools share similar CLI conventions, configure through pyproject.toml, and install as single binaries.
Large, partially-typed codebases: ty’s gradual guarantee means you can add annotations file by file without triggering cascading errors. This is the strongest argument for ty over mypy or pyright on existing code.
Teams wanting one tool for CI and editors: ty’s single binary eliminates the split between a CLI checker for CI and a separate language server for editor integration.
When to wait: ty is in beta. If your project depends on mypy plugins for frameworks like Django, Pydantic, or SQLAlchemy, ty cannot replace mypy yet because it has no plugin system. The GitHub tracking issue tracks feature coverage.
Important
ty is under active development. Some typing spec features are not yet implemented, and diagnostics may differ from mypy or pyright. Track the feature status issue for current coverage.
How ty compares to alternatives
| Feature | ty | mypy | pyright |
|---|---|---|---|
| Speed (vs mypy) | ~10x faster or more | Baseline | 3-5x faster |
| Built-in LSP | Yes | No | Yes (Pylance is closed-source) |
| Gradual guarantee | Yes | No | No |
| Maturity | Beta | Stable (since 2012) | Stable (since 2019) |
For a full comparison including configuration, plugin support, and untyped code handling, see How do mypy, pyright, and ty compare?.
Installation
ty has no dependencies beyond the binary itself. For full installation options, see the ty reference page.
The fastest way to try it on an existing project:
uvx ty checkTo add it as a development dependency:
uv add --dev tyOther installation methods:
# Install as a standalone CLI tool
uv tool install ty
# Via pip or pipx
pip install ty
pipx install tyFor a guided walkthrough including editor setup, see How to try the ty type checker.
Core workflows
Checking a project
Run ty check from your project root to type-check all Python files. You can target specific files or directories:
ty check
ty check src/
ty check src/main.pyTo check against a specific Python version without changing your environment:
ty check --python-version 3.12If ty can’t find your installed packages, point it at your virtual environment:
ty check --python .venvReading diagnostics
ty’s error output shows the relevant code spans with annotations. A typical diagnostic looks like:
error[invalid-argument-type]: Argument to this parameter is incorrect
--> src/main.py:12:20
|
10 | def greet(name: str) -> str:
| ---- Expected `str`
11 | return f"Hello, {name}"
12 | result = greet(42)
| ^^ Cannot assign `int` to parameter of type `str`Each diagnostic includes a rule name in brackets (invalid-argument-type). You can use these names to configure rule severity or suppress individual errors.
Configuring rules
ty rules are configured in pyproject.toml under [tool.ty.rules]. Each rule can be set to "error", "warn", or "ignore":
[tool.ty.rules]
unresolved-import = "ignore"
unused-ignore-comment = "warn"
possibly-missing-import = "error"For files that need different treatment, use overrides with glob patterns:
[[tool.ty.overrides]]
include = ["src/legacy/**"]
rules = { unresolved-attribute = "ignore", invalid-assignment = "ignore" }You can also create a standalone ty.toml file. When both exist, ty.toml takes precedence over pyproject.toml for all ty settings.
Suppressing individual errors
Add an inline comment with the rule name to suppress a specific diagnostic:
result = greet(42) # ty: ignore[invalid-argument-type]For projects with many existing errors, the --add-ignore flag inserts suppression comments throughout your codebase automatically. This establishes a baseline so you can enforce type checking on all new code:
ty check --add-ignoreUsing the language server
ty includes a full LSP implementation in the same binary. Start it with:
ty serverThe language server provides completions with auto-import, go-to-definition, find references, rename, inlay hints, hover information, and signature help. Because the server uses the same type analysis as ty check, editor diagnostics match CLI output exactly.
Editor integration
VS Code and Cursor: Install the official ty extension (astral-sh.ty) from the VS Code Marketplace. Disable the built-in Python language server and Pylance by adding "python.languageServer": "None" to your settings.json.
Neovim: Version 0.11+ has built-in support via vim.lsp.enable('ty'). Earlier versions (0.10) can use nvim-lspconfig.
Zed: Built-in support with no installation required.
PyCharm: Native support starting with version 2025.3, configurable under Python | Tools | ty.
Other editors: Any editor with LSP support can connect to ty server.
For step-by-step editor setup instructions, see How to try the ty type checker.
Migrating from mypy or pyright
ty checks all code by default, including unannotated functions. Projects migrating from mypy (which skips unannotated code by default) often see a large increase in reported errors. This is expected behavior, not a bug.
The migration path typically involves:
- Running
ty checkto see the baseline error count - Using
--add-ignoreto suppress existing errors - Configuring rules to match your team’s tolerance
- Gradually fixing suppressed errors over time
Configuration concepts map between tools, but the syntax differs. For example, mypy’s ignore_missing_imports = true becomes rules.unresolved-import = "ignore" in ty. The exclusion patterns also differ: mypy uses regex while ty uses glob patterns.
For the full migration process with configuration mappings and a phased checklist, see How to migrate from mypy to ty.
Using ty with Ruff and uv
ty fills the type-checking gap in Astral’s Python toolchain. Ruff handles linting and formatting, uv manages packages and environments, and ty checks types. The three tools share design principles: single Rust binaries, fast execution, and configuration in pyproject.toml.
A typical pyproject.toml using all three:
[tool.ruff]
line-length = 88
[tool.ruff.lint]
select = ["E", "F", "I"]
[tool.ty.environment]
python-version = "3.12"
[tool.ty.rules]
unresolved-import = "warn"For CI setup with all three tools, see How to use ty in CI.
Troubleshooting
Warning
Common issues when first running ty:
- Unresolved imports: If ty reports
unresolved-importfor packages you know are installed, point ty at your virtual environment with--python .venvor setenvironment.python = ".venv"in your configuration. - Unexpected errors on untyped code: ty checks all code by default, unlike mypy. If you’re migrating from mypy and see hundreds of new errors, this is expected. Use
--add-ignoreto establish a baseline, or configure rules to ignore specific diagnostic categories.
Version compatibility: When specifying python-version in configuration, ensure your dependencies support that version. ty validates your code against the declared Python version, which may surface errors invisible at runtime.
Learn more
How-to guides
- How to try the ty type checker
- How to migrate from mypy to ty
- How to use ty in CI
- How to gradually adopt type checking in an existing Python project
Explanations
Reference
Get Python tooling updates
Subscribe to the newsletter