# ty: Python Type Checker by Astral

ty (pronounced _tee-why_) is a static type checker and language server for Python from Astral, the creators of [Ruff](https://pydevtools.com/handbook/reference/ruff.md) and [uv](https://pydevtools.com/handbook/reference/uv.md), now part of OpenAI. It performs static analysis on Python code to identify type-related issues before runtime.

{{< callout type="info" >}}
ty was initially known by the code name "Red-Knot" during its early development phase. The tool is in beta, and aims for a 1.0 release.
{{< /callout >}}

## When to use ty

ty is an alternative to the handbook's recommended type checker, [Pyrefly](https://pydevtools.com/handbook/reference/pyrefly.md). Its "gradual guarantee" ensures that adding type annotations to working code never introduces new errors, which makes incremental adoption predictable in a partially-typed codebase. ty also runs 10x to 100x faster than [mypy](https://pydevtools.com/handbook/reference/mypy.md) and [Pyright](https://pydevtools.com/handbook/reference/pyright.md) on cold checks and pairs cleanly with [Ruff](https://pydevtools.com/handbook/reference/ruff.md) and [uv](https://pydevtools.com/handbook/reference/uv.md) in the OpenAI toolchain. Pyrefly is recommended over ty for most new projects because ty is still in beta as of 2026 and its typing-spec conformance trails Pyrefly's; choose ty if the gradual guarantee matters more than feature completeness, or if OpenAI-toolchain coherence is a priority. For a full comparison across all major type checkers, see [How do Python type checkers compare?](https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare.md).

To get started, see [Set up type checking for a Python project with ty](https://pydevtools.com/handbook/tutorial/set-up-type-checking-with-ty.md) for a full walkthrough, or [How to try the ty type checker](https://pydevtools.com/handbook/how-to/how-to-try-the-ty-type-checker.md) for the short version. If you're already using [mypy](https://pydevtools.com/handbook/reference/mypy.md) or [pyright](https://pydevtools.com/handbook/reference/pyright.md), 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).

## Key Features

*   Performance: 10x to 100x faster than mypy and Pyright on cold checks (home-assistant: ty at 2.19s vs mypy at 45.66s). Fine-grained incremental analysis provides near-instant (sub-5ms) feedback in editor mode.
*   Diagnostics: Detailed error messages with code-span annotations and rich contextual information.
*   Language Server: Full LSP implementation with go-to-definition, go-to-declaration, go-to-type-definition, find references, completions with auto-import, rename refactoring, inlay hints, hover, signature help, quick fixes, semantic highlighting, and code folding.
*   Configurable Rules: Each diagnostic rule can be set to error, warn, or ignore. Supports per-file overrides, trailing `# ty: ignore[rule-code]` suppression comments, and own-line suppression comments placed on the line immediately above the offending code.
*   Gradual Guarantee: Adding type annotations to working code never introduces new errors. Annotations only narrow existing errors, which makes incremental adoption predictable.
*   Advanced Type System: First-class intersection types, type narrowing (including `hasattr` narrowing), and reachability analysis based on type inference.
*   Notebook Support: Language server features for Jupyter notebooks with cross-cell analysis.
*   Pydantic Support: First-class Pydantic modeling. Distinguishes lax and strict validation modes, follows Pydantic's coercion rules on model constructors, parses `model_config = ConfigDict(...)` keys (`strict`, `frozen`, `extra`, `validate_by_name`, `validate_by_alias`, `populate_by_name`), honors `extra="forbid"`, supports field aliases including `validation_alias`, reads field metadata from `Field` and `Annotated` (including constraints like `max_length`), handles mixin class fields, treats `BaseSettings` fields as optional by default, supports `RootModel`, synthesizes `__replace__` for Pydantic models, and allows private attributes on frozen models to be mutated.
*   PEP 723 Script Isolation: ty type-checks [PEP 723](https://pydevtools.com/handbook/explanation/what-is-pep-723.md) inline-script files in isolation, using a separate dependency search path distinct from the project's virtual environment. The declared `requires-python` and platform settings in the script's metadata block are respected. Use `--exclude-scripts` to skip PEP 723 scripts during a project check.
*   Dependency Checking (Preview): The `missing-direct-dependency` rule flags imports that resolve through transitive dependencies rather than packages declared in `project.dependencies` or `project.optional-dependencies`. This prevents breakage if an upstream package drops a dependency the project imports indirectly. Requires uv integration (`TY_UV=1`) and a synchronized environment; `uv check` combines the sync and check in one step. Enable via `missing-direct-dependency = "error"` under `[tool.ty.rules]`. The rule also checks PEP 723 scripts against their inline `dependencies` list when `TY_UV=1` or `TY_UV=scripts` is set.

## Type System Features

ty implements several type system features beyond what other type checkers provide:

*   Redeclarations: Allows reusing the same symbol with a different type within a function scope.
*   Intersection Types: First-class support for intersection types (`A & B`), which enables more precise type narrowing after `isinstance` checks.
*   Reachability Analysis: Uses type inference to detect unreachable branches, which can handle version-specific code paths for libraries like pydantic.
*   Fixpoint Iteration: Infers types for symbols that cyclically depend on themselves by iterating until the type converges.
*   Variadic Generics: Supports PEP 646 variadic generics (`TypeVarTuple`, `Unpack[Ts]`) in function signatures and generic classes.

## Installation

The quickest way to run ty is with [uvx](https://docs.astral.sh/uv/guides/tools/):

```shell
uvx ty check
```

For project use, add ty as a development dependency:

```shell
uv add --dev ty
uv run ty check
```

ty can also be installed globally with `uv tool install ty`, via pip, pipx, or using standalone installers available for macOS, Linux, and Windows.

## Basic Usage

```shell
# Check the current project
ty check

# Check specific files
ty check src/main.py

# Check with a specific Python version target
ty check --python-version 3.12

# Get an explanation of a specific rule
ty explain rule <rule-name>

# Show all rules
ty explain rule
```

## Configuration

ty reads configuration from `pyproject.toml` (under `[tool.ty]`) or a dedicated `ty.toml` file. Rule levels and other settings can be configured per-project:

```toml
[tool.ty.rules]
unused-ignore-comment = "warn"
possibly-missing-import = "error"
```

User-level configuration is also supported at `~/.config/ty/ty.toml`.

For single-file scripts, ty reads `rules` and `analysis` configuration from [PEP 723](https://pydevtools.com/handbook/explanation/what-is-pep-723.md) `# /// script` inline metadata blocks, enabling per-script configuration without a `pyproject.toml`. ty also checks PEP 723 scripts in isolation: each script uses a separate dependency search path from the project's virtual environment, and `requires-python` and platform settings from the metadata block are respected. Pass `--exclude-scripts` to skip PEP 723 scripts during `ty check`.

## Editor Integration

ty includes official editor support:

*   VS Code: Install the [ty extension](https://marketplace.visualstudio.com/items?itemName=astral-sh.ty) from the VS Code Marketplace.
*   Neovim: Configure via `nvim-lspconfig` or the built-in `vim.lsp.config` (Neovim 0.11+).
*   Zed: Built-in support (can be enabled in settings).
*   PyCharm: Native ty support.
*   Emacs: Compatible via the built-in Eglot client (Emacs 29+).

For other editors, run `ty server` to start the language server.

## Pre-commit Integration

ty has an official pre-commit hook at [`astral-sh/ty-pre-commit`](https://github.com/astral-sh/ty-pre-commit), compatible with both [pre-commit](https://pydevtools.com/handbook/how-to/how-to-set-up-pre-commit-hooks-for-a-python-project.md) and [prek](https://pydevtools.com/handbook/reference/prek.md):

```yaml
repos:
  - repo: https://github.com/astral-sh/ty-pre-commit
    rev: v0.0.80
    hooks:
      - id: ty
```

The hook invokes ty through uv, making dependencies declared in `pyproject.toml` resolvable during the check. It runs against the whole project rather than only the staged files, since a change in one module can introduce type errors in another. The `--isolated` argument prevents the hook from creating or modifying a lockfile or virtual environment.

## Comparison to Other Tools

ty is not a drop-in replacement for [mypy](https://pydevtools.com/handbook/reference/mypy.md) or [pyright](https://pydevtools.com/handbook/reference/pyright.md). It makes different design choices and has different default behaviors. The primary differentiators are speed (10x to 100x faster than mypy and Pyright on cold checks, with home-assistant checking in 2.19s versus mypy's 45.66s) and a gradual guarantee that adding annotations to working code never introduces new errors. ty checks all code by default, including unannotated function bodies that mypy skips, so a mypy-clean codebase can surface many new errors when first checked with ty ([how mypy, ty, and Pyrefly handle untyped code](https://pydevtools.com/handbook/explanation/how-mypy-ty-and-pyrefly-handle-untyped-code.md) compares all three). ty aims for conformance with the Python typing specification.

{{< callout type="warning" >}}
ty is in beta. Some features may be missing or behave differently compared to mature type checkers. Check the [tracking issue](https://github.com/astral-sh/ty/issues/1889) for type system feature status.
{{< /callout >}}

## Cons

* Pre-1.0 and moving fast: ty is in beta on the 0.x line, so defaults and diagnostics still change between releases. Pin the version anywhere its output gates a build.
* Incomplete type-system coverage: some features from the Python typing specification are still in progress, tracked in [astral-sh/ty#1889](https://github.com/astral-sh/ty/issues/1889).
* Not a drop-in for mypy or pyright: ty checks all code by default, including unannotated function bodies that mypy skips, so a codebase that passes mypy can surface many new errors on its first ty run.
* Young ecosystem: ty has fewer editor plugins, CI recipes, and community answers than mypy's decade-old ecosystem, and it is developed by a single vendor (Astral, now part of OpenAI).
