Cybersecurity-Projects/PROJECTS/bug-bounty-platform/docs/research/TY.md

12 KiB

ty - Extremely Fast Python Type Checker

Official Docs: https://docs.astral.sh/ty

What is ty?

ty is an extremely fast Python type checker written in Rust by Astral (the creators of uv and Ruff). It's designed to be:

  • 10-100x faster than mypy and pyright
  • Zero configuration to get started
  • Compatible with existing type annotations
  • Production-ready for large codebases

Think: "Ruff for type checking" - blazing fast, modern, and built for scale.


Installation

Add to your project dependencies:

# With uv (recommended)
uv add --dev ty

# With pip
pip install ty

Or run it directly without installing:

uvx ty check

Quick Start

1. Basic Usage

# Check entire project
ty check

# Check specific files/directories
ty check src/
ty check src/models/User.py

# Watch mode (recheck on file changes)
ty check --watch

2. Exit Codes

  • 0 - No errors
  • 1 - Type errors found
  • 2 - Invalid config/CLI options
  • 101 - Internal error

3. Output Formats

# Default verbose output with context
ty check

# Concise (one per line)
ty check --output-format concise

# GitHub Actions annotations
ty check --output-format github

# GitLab Code Quality JSON
ty check --output-format gitlab

Configuration

[tool.ty]
# Python version (auto-detected from requires-python if not set)
python-version = "3.12"

# Source directories
[tool.ty.src]
include = ["src", "tests"]
exclude = ["src/generated/**", "*.proto"]

# Python environment (auto-detected from .venv if not set)
[tool.ty.environment]
root = ["./src"]
python = "./.venv"

# Rule severity configuration
[tool.ty.rules]
# Make warnings errors
possibly-missing-attribute = "error"
possibly-missing-import = "error"

# Downgrade errors to warnings
division-by-zero = "warn"

# Disable specific rules
redundant-cast = "ignore"
unused-ignore-comment = "ignore"

# Override rules for specific files
[[tool.ty.overrides]]
include = ["tests/**"]
[tool.ty.overrides.rules]
unresolved-reference = "warn"

# Terminal output
[tool.ty.terminal]
error-on-warning = false  # exit code 1 if warnings exist
output-format = "full"    # full | concise | github | gitlab

Option 2: ty.toml (Alternative)

Create backend/ty.toml (same structure, no [tool.ty] prefix):

python-version = "3.12"

[src]
include = ["src", "tests"]

[rules]
possibly-unresolved-reference = "warn"

Important Rules

Error-Level (Default)

These will fail your CI/CD:

Rule What it catches
call-non-callable Calling non-callable objects: 4()
division-by-zero Division by zero: 5 / 0
unresolved-import Missing modules: import nonexistent
unresolved-reference Undefined variables: print(undefined_var)
unresolved-attribute Missing attributes: obj.missing_attr
invalid-argument-type Wrong arg types: func(x: int) called with func("str")
invalid-return-type Return type mismatch
missing-argument Missing required args: func(x: int) called as func()
unknown-argument Unknown kwargs: func(x=1, unknown=2)
unsupported-operator Bad operators: "string" + 123
invalid-assignment Type mismatch: x: int = "string"

Warning-Level (Default)

Won't fail CI unless you enable --error-on-warning:

Rule What it catches
possibly-unresolved-reference Variables that might not be defined (conditional)
possibly-missing-attribute Attributes that might not exist (conditional)
possibly-missing-import Imports that might be missing (conditional)
redundant-cast Unnecessary cast() calls
deprecated Usage of deprecated APIs
undefined-reveal reveal_type() without importing it

Ignore-Level (Disabled by Default)

Must explicitly enable:

Rule What it catches
unused-ignore-comment Unused # type: ignore or # ty: ignore
possibly-unresolved-reference Possibly undefined refs in conditional code
division-by-zero Preview rule - division by zero

Suppression Comments

ty-specific suppression

# Suppress specific rule
result = unsafe_operation()  # ty: ignore[invalid-argument-type]

# Suppress multiple rules
value = risky()  # ty: ignore[unresolved-attribute, invalid-return-type]

# Multi-line expressions (comment on first OR last line)
result = long_function(  # ty: ignore[missing-argument]
    arg1,
    arg2
)

# Combine with other tools
x = 1  # ty: ignore[division-by-zero]  # fmt: skip

Standard type: ignore (PEP 484)

# ty respects standard type: ignore
result = something()  # type: ignore

# But ty: ignore is preferred for specificity
result = something()  # ty: ignore[invalid-return-type]

Disable all checking in a function

from typing import no_type_check

@no_type_check
def untyped_function():
    return "anything" + 123  # no errors

Check for unused suppressions

[tool.ty.rules]
unused-ignore-comment = "warn"  # warn about unused suppressions

Common Configurations for Production

[tool.ty.rules]
# Treat all "possibly" rules as errors
possibly-missing-attribute = "error"
possibly-missing-import = "error"
possibly-unresolved-reference = "error"

# Catch unused suppressions
unused-ignore-comment = "warn"

# Stricter terminal behavior
[tool.ty.terminal]
error-on-warning = true
[tool.ty.rules]
# Downgrade strict rules to warnings
unresolved-attribute = "warn"
invalid-argument-type = "warn"

# Focus on critical errors only
[tool.ty.terminal]
error-on-warning = false

FastAPI-Specific

[[tool.ty.overrides]]
include = ["src/routes/**", "src/dependencies/**"]

[tool.ty.overrides.rules]
# FastAPI uses runtime dependency injection
unresolved-reference = "warn"  # for Depends() params

CLI Flags Reference

Rule Control

# Override rule severity
ty check --error possibly-unresolved-reference
ty check --warn division-by-zero
ty check --ignore redundant-cast

# Can combine multiple
ty check --error rule1 --warn rule2 --ignore rule3

Environment

# Specify Python environment
ty check --python .venv

# Python version
ty check --python-version 3.12

# Platform
ty check --python-platform linux
ty check --python-platform all  # no platform assumptions

Output Control

# Verbosity
ty check -v      # verbose
ty check -vv     # very verbose
ty check -q      # quiet
ty check -qq     # silent

# Exit codes
ty check --exit-zero           # always exit 0
ty check --error-on-warning    # warnings = exit 1

Environment Variables

# Log level (for debugging ty itself)
TY_LOG=debug ty check
TY_LOG=trace ty check

# Parallelism limit
TY_MAX_PARALLELISM=4 ty check

# Profile performance
TY_LOG_PROFILE=1 ty check  # creates tracing.folded

# Python path (additional search paths)
PYTHONPATH=/extra/path ty check

# Virtual environment
VIRTUAL_ENV=/path/to/.venv ty check

Integration

CI/CD (GitHub Actions)

name: Type Check

on: [push, pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: astral-sh/setup-uv@v5

      - name: Install dependencies
        run: uv sync --all-extras

      - name: Type check
        run: uv run ty check --output-format github

Pre-commit Hook

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ty
    rev: v0.0.1  # use latest version
    hooks:
      - id: ty

VS Code

// .vscode/settings.json
{
  "python.linting.enabled": true,
  "python.linting.tyEnabled": true,
  "python.linting.tyArgs": ["check"],
}

Just/Makefile

# Makefile
.PHONY: typecheck
typecheck:
	ty check

.PHONY: typecheck-watch
typecheck-watch:
	ty check --watch

ty vs mypy vs pyright

Feature ty mypy pyright
Speed 🚀 10-100x faster Baseline Fast (but slower than ty)
Language Rust Python TypeScript
Config Minimal (auto-detects) Verbose Verbose
Strictness Configurable Very strict Very strict
IDE Support Growing Excellent Excellent (VSCode)
Ecosystem New (2024) Mature (2012) Mature (2019)
Plugin Support Limited Extensive Limited
Adoption Early Industry standard Microsoft standard

Migration from mypy

ty is mostly compatible with mypy. You can run both in parallel:

[tool.ty.rules]
# Map mypy behavior to ty
invalid-argument-type = "error"  # mypy: arg-type
invalid-return-type = "error"    # mypy: return-value
unresolved-attribute = "error"   # mypy: attr-defined

Key differences:

  • ty is faster but less mature
  • mypy has more plugins (e.g., sqlalchemy, django)
  • ty auto-detects more (less config needed)
  • ty focuses on speed, mypy on completeness

Recommendation: Use ty in dev for fast feedback, keep mypy in CI for comprehensive checks (for now).


Troubleshooting

ty can't find my virtual environment

# Explicitly specify
ty check --python .venv

# Or in pyproject.toml
[tool.ty.environment]
python = "./.venv"

False positives in generated code

[tool.ty.src]
exclude = ["src/generated/**", "alembic/versions/**"]

ty is too strict

# Downgrade specific rules
[tool.ty.rules]
possibly-missing-attribute = "warn"
possibly-unresolved-reference = "warn"

Performance profiling

# Generate flamegraph
TY_LOG_PROFILE=1 ty check

# View with flamegraph.pl or speedscope.app

Best Practices for This Project

1. Use ty for fast local development

# Quick checks while coding
ty check --watch

2. Keep mypy for CI completeness

# Both in CI
- run: ty check              # fast, catches most issues
- run: mypy src/             # thorough, catches edge cases

3. Suppress intentional violations

# FastAPI dependency injection
async def get_db(db: Annotated[AsyncSession, Depends(get_db_session)]):
    # ty might not understand Depends()
    return db  # ty: ignore[invalid-return-type]

4. Configure for async/SQLAlchemy

[[tool.ty.overrides]]
include = ["src/repositories/**", "src/services/**"]

[tool.ty.overrides.rules]
# Async/SQLAlchemy patterns ty might not understand yet
unresolved-attribute = "warn"

Key Takeaways

DO:

  • Use ty check --watch during development
  • Configure pyproject.toml for your project
  • Enable unused-ignore-comment to keep suppressions clean
  • Use --error-on-warning in CI for strictness

DON'T:

  • Blindly suppress errors (investigate first)
  • Use # type: ignore without rule codes
  • Disable important rules globally (use overrides)
  • Expect feature parity with mypy (yet)

Quick Reference Card

# Development
ty check                           # check everything
ty check --watch                   # watch mode
ty check src/models/               # specific directory

# CI/CD
ty check --error-on-warning        # warnings = errors
ty check --output-format github    # GitHub annotations

# Debugging
ty check -vv                       # very verbose
TY_LOG=debug ty check              # ty internal logs

# Configuration
ty check --python .venv            # specify venv
ty check --python-version 3.12     # specify version
ty check --error rule-name         # override rule severity

Resources


Last Updated: 2025-12-06 ty Version: 0.0.1-alpha.30+ Maintained By: Astral (creators of uv, Ruff)