ty: The Blazingly Fast Python Type Checker from Astral (Ruff & uv Creators)

Published: (January 6, 2026 at 11:44 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

Key Features

  • ⚡ Blazingly Fast – 10–100× faster than mypy and Pyright
  • 🔍 Rich Diagnostics – Detailed error messages with multi‑file context
  • 🧠 Smart Type Inference – Catches bugs even without type annotations
  • 🎯 Advanced Type System – Intersection types, advanced narrowing, reachability analysis
  • 🛠️ Language Server – Built‑in support for IDE integration (VS Code extension available)

Installation

# Using uv (recommended)
uv tool install ty@latest

# Using pip
pip install ty

Basic Usage

# Check a file
ty check file.py

# Check directories
ty check src tests

# Verbose mode
ty check src --verbose

What Makes ty Special?

1. Speed That Matters

ty can type‑check the entire Home Assistant project in ~2.19 seconds, compared to mypy’s 45.66 seconds – over 20× faster!

For large codebases, this speed difference transforms the developer experience:

  • No more waiting for CI to finish
  • Instant feedback in your IDE
  • Practical to run on every save

2. Powerful Type Inference

ty can find bugs even without type annotations. Below are some real‑world examples.

Real‑World Bug Detection

Example 1: Type Mismatches

def add(x: int, y: int) -> int:
    return x + y

result: str = add(1, 2)  # Oops! Assigning int to str

ty’s output

error[invalid-assignment]: Object of type `int` is not assignable to `str`
 --> example.py:4:9
  |
4 | result: str = add(1, 2)
  |         ---   ^^^^^^^^^ Incompatible value of type `int`
  |         |
  |         Declared type

Example 2: Missing Attributes

class User:
    def __init__(self, name: str):
        self.name = name

    def get_email(self):
        return self.email  # email was never defined!

ty catches this

error[unresolved-attribute]: Object of type `Self@get_email` has no attribute `email`
 --> example.py:6:16
  |
6 |         return self.email
  |                ^^^^^^^^^^

Even for more complex cases:

class DatabaseClient:
    def __init__(self, connection_string: str):
        self.connection = connect(connection_string)

    def query(self, sql: str):
        # Typo: should be .execute(), not .exec()
        return self.connection.exec(sql)

ty will warn you that .exec() doesn’t exist on the connection object.

Example 3: Incorrect Function Arguments

numbers: list[int] = [1, 2, 3]
numbers.append("four")  # String in int list!

ty’s error

error[invalid-argument-type]: Argument to bound method `append` is incorrect
 --> example.py:2:16
  |
2 | numbers.append("four")
  |                ^^^^^^ Expected `int`, found `Literal["four"]`

Example 4: Null Safety

def process(value: str | None) -> int:
    return len(value)  # What if value is None?

ty spots the issue

error[invalid-argument-type]: Expected `Sized`, found `str | None`
 --> example.py:2:16
  |
2 |     return len(value)
  |                ^^^^^
  |
info: Element `None` of this union is not assignable to `Sized`

Example 5: Implicit None Returns

def get_name(user_id: int) -> str:
    if user_id > 0:
        return "User"
    # Missing return statement – implicit None!

ty catches this too

error[invalid-return-type]: Function can implicitly return `None`,
which is not assignable to return type `str`

Configuration

ty uses pyproject.toml for configuration:

[tool.ty]

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

[tool.ty.src]
include = ["src/**/*.py", "tests/**/*.py"]
exclude = [".tox/**", "build/**", "dist/**"]

# Per‑directory overrides
[[tool.ty.overrides]]
include = ["tests/**/*.py"]
[tool.ty.overrides.rules]
invalid-assignment = "ignore"  # More lenient for tests

CI/CD Integration

GitHub Actions

name: Type Check
on: [push, pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v5
        with:
          python-version: '3.10'
      - name: Install dependencies
        run: pip install ty
      - name: Run type checker
        run: ty check src tests

tox Integration

[testenv:ty]
deps =
    ty
    -e .
commands =
    ty check src tests

pre‑commit Hook

repos:
  - repo: local
    hooks:
      - id: ty
        name: ty type checker
        entry: ty check src tests
        language: system
        pass_filenames: false
        types: [python]

Enjoy the speed and safety that ty brings to your Python projects!

Editor Integration

VS Code

  • Install the “ty” extension from the VS Code Marketplace.

Enjoy automatic:

  • Type checking as you type
  • Inlay hints for inferred types
  • Code actions and quick fixes
  • Jump‑to‑definition with type awareness

ty vs mypy vs Pyright

FeaturetymypyPyright
Speed⚡⚡⚡ Ultra‑fast🐢 Moderate🚀 Fast
LanguageRustPythonTypeScript
Error Messages📝 Very detailed📄 Standard📝 Detailed
Type Inference🧠 Powerful📚 Standard🧠 Powerful
Maturity🆕 Beta✅ Stable✅ Stable
Diagnostics🔍 Multi‑file context📊 Single‑file🔍 Cross‑file
Language Server✅ Built‑in⚠️ Via dmypy✅ Built‑in

Current Limitations

As of v0.0.9 (Beta):

  • Limited rule set – Main rules implemented; more coming in 2026.
  • No strict mode yet – Won’t complain about missing type annotations.
  • Beta status – API may change before the stable release.

Even in beta, ty already catches real bugs and provides value in production codebases.

Getting Started with ty

Step 1: Install and Run

uv tool install ty@latest
ty check src

Step 2: Review Results

ty will show you actual bugs in your code, even without type annotations!

Step 3: Add to CI

# Add to your test script
tox -e ty

# Or run directly
ty check src tests

Step 4: Gradual Type Annotation

# Before
def calculate_total(items):
    return sum(item.price for item in items)

# After
def calculate_total(items: list[Item]) -> Decimal:
    return sum(item.price for item in items)

With annotations, ty becomes even more powerful!

Real‑World Example: FastAPI Application

from fastapi import FastAPI, HTTPException

app = FastAPI()

class UserService:
    def __init__(self, db_url: str):
        self.db = connect_database(db_url)

    def get_user(self, user_id: int):
        user = self.db.query(User).filter(User.id == user_id).first()
        if user:
            return user
        # Bug: FastAPI expects HTTPException, but we're returning None!
        return None

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    service = UserService(DB_URL)
    user = service.get_user(user_id)
    # Bug: user could be None, but we're accessing .dict()
    return user.dict()

ty will catch both bugs:

  1. get_user can return None, but FastAPI expects an exception or a valid user.
  2. user.dict() could fail if user is None.

Performance Tips

  • Use file exclusion – Skip generated files and vendor directories.
  • Enable cachingty caches results for unchanged files.
  • Parallel processingty automatically uses multiple cores.
  • Incremental mode – In your editor, only changed files are re‑checked.

Roadmap

According to Astral, ty targets a stable 1.0 release in 2026, with plans for:

  • ✅ More comprehensive rule coverage
  • ✅ Strict mode (enforce type annotations)
  • ✅ Better integration with popular frameworks
  • ✅ Plugin system for custom rules
  • ✅ Performance optimizations

Conclusion

ty represents the next evolution in Python type checking. Its combination of blazing speed, powerful inference, and excellent diagnostics makes it a compelling choice for Python developers.

While still in beta, ty is already proving valuable for catching real bugs and improving code quality. If you’re using mypy or Pyright and are frustrated by slow check times, ty is worth trying.

The Astral team has an excellent track record with Ruff and uv, and ty looks set to be another game‑changer in the Python tooling ecosystem.

Resources

  • 🌐 Official Website:
  • 📚 Documentation:
  • 💻 GitHub:
  • 💬 Discord:

Have you tried ty yet? What’s your experience with Python type checkers? Let me know in the comments! 👇

Back to Blog

Related posts

Read more »

How uv got so fast

Article URL: https://nesbitt.io/2025/12/26/how-uv-got-so-fast.html Comments URL: https://news.ycombinator.com/item?id=46393992 Points: 108 Comments: 30...