Skip to content
Dev Tools Beginner Tutorial

Catch Python Bugs Before Runtime with Astral's ty Type Checker

Install Astral's blazing-fast ty, wire it into VS Code and pre-commit, and stop shipping type errors.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Jul 29, 2026 · 4 min read
Catch Python Bugs Before Runtime with Astral's ty Type Checker

What you'll build

A Python project where type errors can't reach runtime: ty — the Rust-based type checker from Astral, the team behind uv and Ruff — checking your code from the CLI, flagging mistakes live in VS Code, and blocking bad commits with pre-commit.

Prerequisites

  • Python 3.8 or newer (this tutorial was verified on Python 3.13.5, macOS).
  • Versions verified: ty 0.0.64 (released 2026-07-27), ty-pre-commit v0.0.64, VS Code extension astral-sh.ty 2026.64.0.
  • git and pip (or uv) on your PATH.
  • Note: ty is in beta, with 1.0 targeted for 2026. Diagnostics and defaults can shift between releases, so pin the version anywhere your team shares config.

1. Install ty

Pick whichever matches your setup:

uv tool install ty@latest    # uv users
pip install ty               # plain pip

For one-off runs without installing anything, uvx ty check also works. Confirm the install:

ty --version
ty 0.0.64 (5e64a131b 2026-07-27)

2. Create a project with a type bug

mkdir -p ty-demo/src && cd ty-demo

Create src/billing.py with two classic runtime landmines — a string passed where a number belongs, and a typo'd variable name:

def apply_discount(price: float, percent: int) -> float:
    return price * (1 - percent / 100)


def format_total(total: float) -> str:
    return f"${total:.2f}"


subtotal = apply_discount("100", 15)
print(format_total(subtotal))
print(format_total(missing_var))

3. Run your first check

ty check
error[invalid-argument-type]: Argument to function `apply_discount` is incorrect
 --> src/billing.py:9:27
  |
9 | subtotal = apply_discount("100", 15)
  |                           ^^^^^ Expected `int | float`, found `Literal["100"]`
  |
info: Function defined here
 --> src/billing.py:1:5
  |
1 | def apply_discount(price: float, percent: int) -> float:
  |     ^^^^^^^^^^^^^^ ------------ Parameter declared here
  |

error[unresolved-reference]: Name `missing_var` used when not defined
  --> src/billing.py:11:20
   |
11 | print(format_total(missing_var))
   |                    ^^^^^^^^^^^
   |

Found 2 diagnostics

Both bugs caught without executing a line of code — and the check exits non-zero, which is what makes it CI-enforceable. Fix them by replacing src/billing.py with:

def apply_discount(price: float, percent: int) -> float:
    return price * (1 - percent / 100)


def format_total(total: float) -> str:
    return f"${total:.2f}"


subtotal = apply_discount(100.0, 15)
print(format_total(subtotal))

4. Configure ty in pyproject.toml

ty reads config from [tool.ty] in pyproject.toml (or a standalone ty.toml). Create pyproject.toml:

[project]
name = "ty-demo"
version = "0.1.0"
requires-python = ">=3.13"

[tool.ty.environment]
python-version = "3.13"

[tool.ty.rules]
possibly-unresolved-reference = "warn"

Each rule can be set to "error", "warn", or "ignore" — handy for adopting ty gradually on a loosely typed codebase.

5. Wire it into VS Code

Install the ty extension (ID astral-sh.ty). It bundles ty's language server, so you get the same diagnostics inline as you type, plus go-to-definition and completions. The extension automatically disables the Python extension's language server to avoid running two at once; override that with the python.languageServer and ty.disableLanguageServices settings if you want Pylance features alongside. PyCharm 2025.3+, Neovim, Zed, and Emacs setups are covered in the editors docs.

6. Add the pre-commit hook

pip install pre-commit
git init && git add -A

Create .pre-commit-config.yaml:

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

Then activate it:

pre-commit install

Unlike most hooks, this one checks your whole project rather than just staged files — deliberately, since a commit touching only a.py can surface new errors in b.py.

Verify it works

pre-commit run --all-files
ty.......................................................................Passed

And the direct check on your fixed code:

ty check
All checks passed!

To see the gate in action, reintroduce the "100" bug from step 2 and try git commit — the hook fails and the commit is blocked until ty check is clean.

Troubleshooting

error[unresolved-import]: Cannot resolve imported module requests`` — ty resolves third-party imports against a Python environment, and the package isn't in the one it picked (the info: lines under the error list every path it searched). Install the dependency into your project's .venv, or point ty at the right environment with ty check --python .venv. With an activated virtualenv or a uv-managed project, resolution is automatic.

ty: command not found right after installinguv tool install places binaries in ~/.local/bin, which may not be on your PATH; run uv tool update-shell and open a new terminal. With plain pip inside a virtualenv, the binary lands in the venv's bin/ (Windows: Scripts\) directory, so the venv must be activated.

The ty hook fails on pre-commit.ci — the hook resolves your project's dependencies at run time, which requires network access that pre-commit.ci doesn't allow. Add ci: skip: [ty] to your config and run ty check as a regular step in your CI pipeline instead. Standard pre-commit in GitHub Actions works fine.

Next steps

  • Browse the rules reference to tune severities per rule, and use ty check --add-ignore to bulk-insert ty: ignore suppression comments when onboarding a legacy codebase.
  • Try ty check --fix to auto-apply available fixes.
  • Experiment with diagnostics in the ty playground before committing to config changes.
  • Read the configuration docs for ty.toml, per-user config, and precedence rules.

Sources & further reading

  1. Installing ty — docs.astral.sh
  2. Configuring ty — docs.astral.sh
  3. Editor integration — docs.astral.sh
  4. ty-pre-commit — github.com
  5. ty on PyPI — pypi.org
  6. ty extension for VS Code — marketplace.visualstudio.com
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 0

Join the discussion

Sign in or create an account to comment and vote.

No comments yet

Be the first to weigh in.

Related Reading