# ty: A Complete Guide to Python's Fastest Type Checker


[ty](https://pydevtools.com/handbook/reference/ty.md) is a Python type checker and language server built by Astral, the team behind [Ruff](https://pydevtools.com/handbook/reference/ruff.md) and [uv](https://pydevtools.com/handbook/reference/uv.md) that OpenAI acquired in 2026. It checks Python code for type errors an order of magnitude faster than [mypy](https://pydevtools.com/handbook/reference/mypy.md). 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

ty's **gradual guarantee** makes incremental type adoption safe: adding 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 existing errors rather than creating new ones.

This matters most in large codebases where adding types has historically been risky, all-or-nothing work. ty also ships as a single binary with no runtime dependencies, so there is no separate language server to install and no need for a Node.js or Python runtime to power the tool.

ty also checks all code by default, including unannotated functions. Existing type checkers handle this differently. [mypy](https://pydevtools.com/handbook/reference/mypy.md) skips unannotated functions unless you opt in with `--check-untyped-defs`, which means partially-typed projects get incomplete coverage. [pyright](https://pydevtools.com/handbook/reference/pyright.md) checks everything but requires Node.js, and its best editor experience lives in Pylance, a closed-source VS Code extension.

For a detailed feature-by-feature breakdown, see [How do mypy, pyright, and ty compare?](https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare.md).

## When to use ty

New projects using uv and Ruff: ty completes the OpenAI 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. And because the same binary powers both `ty check` and the language server, teams get identical diagnostics in CI and in their editors without maintaining separate tools.

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](https://github.com/astral-sh/ty/issues/1889) 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](https://github.com/astral-sh/ty/issues/1889) for current coverage.

## How ty compares to alternatives

| Feature | ty | [mypy](https://pydevtools.com/handbook/reference/mypy.md) | [pyright](https://pydevtools.com/handbook/reference/pyright.md) | [Pyrefly](https://pydevtools.com/handbook/reference/pyrefly.md) |
|---|---|---|---|---|
| Speed (vs mypy) | ~10x faster or more | Baseline | 2-3x slower on current benchmarks (older "3-5x faster" numbers predate mypy 1.18+) | 10-50x faster on large codebases |
| Built-in LSP | Yes | No | Yes (Pylance is closed-source) | Yes |
| Gradual guarantee | Yes | No | No | No |
| Maturity | Beta | Stable (since 2012) | Stable (since 2019) | Stable (1.0.0, May 2026) |

For a full comparison including configuration, plugin support, and untyped code handling, see [How do mypy, pyright, and ty compare?](https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare.md).

## Installation

ty has no dependencies beyond the binary itself. For full installation options, see the [ty reference page](https://pydevtools.com/handbook/reference/ty.md).

The fastest way to try it on an existing project:

```bash
uvx ty check
```

To add it as a development dependency:

```bash
uv add --dev ty
```

Other installation methods:

```bash
# 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](https://pydevtools.com/handbook/how-to/how-to-try-the-ty-type-checker.md).

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

```bash
ty check
ty check src/
ty check src/main.py
```

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

```bash
ty check --python-version 3.12
```

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

```bash
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"`:

```toml
[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:

```toml
[[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:

```python
result = greet(42)  # ty: ignore[invalid-argument-type]
```

ty also respects PEP 484's `type: ignore` comments. A bare `# type: ignore` suppresses all diagnostics on that line. To suppress a specific ty rule while remaining compatible with other type checkers, use `# type: ignore[ty:rule-name]`:

```python
result = greet(42)  # type: ignore[ty:invalid-argument-type]
```

You can disable `type: ignore` support in your configuration if you want to require `ty: ignore` exclusively.

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:

```bash
ty check --add-ignore
```

### Using the language server

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

```bash
ty server
```

The language server provides completions with auto-import, go-to-definition, find references, rename, inlay hints, hover information, signature help, semantic syntax highlighting, and document highlighting. 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](https://pydevtools.com/handbook/how-to/how-to-try-the-ty-type-checker.md).

## 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](https://pydevtools.com/handbook/how-to/how-to-migrate-from-mypy-to-ty.md) or [How to migrate from pyright to ty](https://pydevtools.com/handbook/how-to/how-to-migrate-from-pyright-to-ty.md).

## Using ty with Ruff and uv

ty fills the type-checking gap in OpenAI's Python toolchain. [Ruff](https://pydevtools.com/handbook/reference/ruff.md) handles linting and formatting, [uv](https://pydevtools.com/handbook/reference/uv.md) 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:

```toml
[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](https://pydevtools.com/handbook/how-to/how-to-use-ty-in-ci.md).

## 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
- [How to try the ty type checker](https://pydevtools.com/handbook/how-to/how-to-try-the-ty-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 migrate from pyright to ty](https://pydevtools.com/handbook/how-to/how-to-migrate-from-pyright-to-ty.md)
- [How to use ty in CI](https://pydevtools.com/handbook/how-to/how-to-use-ty-in-ci.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)

### Explanations
- [How do mypy, pyright, and ty compare?](https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare.md)

### Reference
- [ty reference page](https://pydevtools.com/handbook/reference/ty.md)
- [ty official documentation](https://docs.astral.sh/ty/)
- [ty playground](https://play.ty.dev)
