ty: Python Type Checker by Astral
ty (pronounced tee-why) is a static type checker and language server for Python built by Astral, the creators of Ruff and uv, now part of OpenAI. It performs static analysis on Python code to identify type-related issues before runtime.
When to use ty
ty is an alternative to the handbook’s recommended type checker, Pyrefly. It checks unannotated function bodies while leaving ordinary unannotated function return types as Unknown by default. Return-type inference can be enabled explicitly. This permits gradual adoption, but adding annotations can expose new errors. ty pairs with Ruff and uv, both built by Astral, now part of OpenAI. It remains in beta; evaluate the typing features and framework behavior required by the project. For a full comparison across all major type checkers, see How do Python type checkers compare?.
To get started, see Set up type checking for a Python project with ty for a full walkthrough, or How to try the ty type checker for the short version. If you’re already using mypy or pyright, see How to migrate from mypy to ty or How to migrate from pyright to ty.
Key Features
- Incremental analysis: reuses prior analysis to update diagnostics after edits.
- 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 typing: uses
Unknownfor missing type information. The gradual guarantee says that making types less precise should not introduce errors; adding precise annotations can reveal errors. - Advanced Type System: First-class intersection types, type narrowing (including
hasattrnarrowing), and reachability analysis based on type inference. - Notebook Support: Language server features for Jupyter notebooks with cross-cell analysis.
- Pydantic support: built-in handling for model constructors and fields. ty does not load mypy plugins; see the framework support FAQ.
- PEP 723 Script Isolation: ty type-checks PEP 723 inline-script files in isolation, using a separate dependency search path distinct from the project’s virtual environment. The declared
requires-pythonand platform settings in the script’s metadata block are respected. Use--exclude-scriptsto skip PEP 723 scripts during a project check. - Dependency Checking (Preview): The
missing-direct-dependencyrule flags imports that resolve through transitive dependencies rather than packages declared inproject.dependenciesorproject.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 checkcombines the sync and check in one step. Enable viamissing-direct-dependency = "error"under[tool.ty.rules]. The rule also checks PEP 723 scripts against their inlinedependencieslist whenTY_UV=1orTY_UV=scriptsis 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 afterisinstancechecks. - 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
Warning
Use ty 0.0.84 or newer for editor integration or ty check --fix on untrusted projects. Versions >=0.0.1a9,<0.0.84 have a use-after-free during incremental analysis that allows a specially crafted project to execute code with the user’s permissions, even without running the project’s Python code. See the upstream security advisory.
The quickest way to run ty is with uvx:
uvx ty checkFor project use, add ty as a development dependency:
uv add --dev ty
uv run ty checkty 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
# 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 invalid-assignment
# Show all rules
ty explain ruleConfiguration
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:
[tool.ty.rules]
unused-ignore-comment = "warn"
possibly-missing-import = "error"ty.toml takes precedence over [tool.ty] in the same directory. ty searches the current directory and its parents. Project settings merge with user settings at ~/.config/ty/ty.toml on macOS/Linux or %APPDATA%\ty\ty.toml on Windows. --config-file accepts a standalone ty-format TOML file. See configuration discovery and precedence.
ty has no --strict preset. Rule severities are configured individually; ty check --error all promotes every rule to an error, including optional checks. ty does not require function annotations; Ruff’s opt-in ANN rules cover that policy. See stricter checking with ty.
Return types for ordinary unannotated functions and methods can be inferred explicitly:
[tool.ty.analysis]
return-type-inference = "always"The default is "never". This setting does not infer asynchronous or generator returns, and does not override explicit annotations. See return-type inference.
For single-file scripts, ty reads rules and analysis configuration from PEP 723 # /// 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 from the VS Code Marketplace.
- Neovim: Configure via
nvim-lspconfigor the built-invim.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, compatible with both pre-commit and prek:
repos:
- repo: https://github.com/astral-sh/ty-pre-commit
rev: v0.0.94
hooks:
- id: ty
args: [--isolated]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 explicit --isolated argument prevents the hook from creating or modifying a project lockfile or virtual environment; the hook’s default invocation can update both. See the hook’s side-effect controls.
Comparison to Other Tools
ty is not a drop-in replacement for mypy or pyright. It makes different design choices and has different default behaviors. 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 compares all three). ty aims for conformance with the Python typing specification.
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.
- 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).
Suppressions and Exit Codes
Use # ty: ignore[invalid-assignment] or # type: ignore[ty:invalid-assignment] to suppress one rule. Bare # type: ignore suppresses every violation on the line; codes without a ty: prefix do not suppress ty diagnostics. unused-ignore-comment detects obsolete ignores when enabled. See ty suppression comments.
ty check exits with 0 for no warnings or errors, 1 for warning- or error-level diagnostics, 2 for configuration, CLI, or I/O errors, and 101 for internal errors. --exit-zero-on-warning allows warnings without failing CI; --exit-zero also allows errors. See ty exit codes.