Skip to content

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

Featuretymypypyright
Speed (vs mypy)~10x faster or moreBaseline3-5x faster
Built-in LSPYesNoYes (Pylance is closed-source)
Gradual guaranteeYesNoNo
MaturityBetaStable (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 check

To add it as a development dependency:

uv add --dev ty

Other installation methods:

# Install as a standalone CLI tool
uv tool install ty

# Via pip or pipx
pip install ty
pipx install ty

For 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.py

To check against a specific Python version without changing your environment:

ty check --python-version 3.12

If ty can’t find your installed packages, point it at your virtual environment:

ty check --python .venv

Reading 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-ignore

Using the language server

ty includes a full LSP implementation in the same binary. Start it with:

ty server

The 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:

  1. Running ty check to see the baseline error count
  2. Using --add-ignore to suppress existing errors
  3. Configuring rules to match your team’s tolerance
  4. 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-import for packages you know are installed, point ty at your virtual environment with --python .venv or set environment.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-ignore to 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

Explanations

Reference

Get Python tooling updates

Subscribe to the newsletter
Last updated on

Please submit corrections and feedback...