← All articles
PYTHON Pyright: Microsoft's Fast Python Type Checker 2026-03-04 · 4 min read · pyright · python · type checking

Pyright: Microsoft's Fast Python Type Checker

Python 2026-03-04 · 4 min read pyright python type checking static analysis mypy pylance vscode typescript

Python's type system — introduced gradually via PEP 484 (2014) and subsequent PEPs — is optional. You can annotate types and get static checking, or ignore them entirely. For projects where you want static checking, two tools dominate: mypy (the reference implementation) and Pyright (Microsoft's type checker, written in TypeScript).

Pyright is faster, integrates natively with VS Code via Pylance, and supports stricter type checking modes. If you're starting a new project or frustrated with mypy's performance on large codebases, Pyright is worth evaluating.

Why Pyright vs. mypy

Speed: Pyright runs significantly faster than mypy, especially with incremental checking. On large codebases, this difference is noticeable during development.

VS Code integration: Pyright powers Pylance, the Python extension for VS Code. If you use VS Code, Pyright is already analyzing your code.

Strict mode: Pyright's strict mode is more aggressive than mypy's --strict, catching additional issues like missing return type annotations and untyped function calls.

TypedDict and dataclasses: Pyright's handling of TypedDict, dataclasses, and protocols is generally considered more accurate than mypy's.

Standard library stubs: Pyright uses its own type stubs for the standard library (typeshed-client) and updates them regularly.

The tradeoff: mypy has been the reference implementation for longer and is more widely used in CI pipelines. Third-party type stub packages sometimes target mypy specifically. For new projects, either is a good choice; Pyright is often preferred for VS Code users.

Installation

With pip:

pip install pyright

With npm (the original distribution):

npm install -g pyright

With uv:

uv tool install pyright

In a project (recommended for CI):

# pyproject.toml approach
[tool.pyright]
venvPath = "."
venv = ".venv"
pip install pyright  # or uv add --dev pyright

Running Pyright

# Check all files in current directory
pyright

# Check a specific file
pyright src/main.py

# Use strict mode
pyright --strict

# Output as JSON (for CI parsing)
pyright --outputjson

Configuration: pyrightconfig.json

Create pyrightconfig.json in your project root:

{
  "pythonVersion": "3.12",
  "pythonPlatform": "Linux",
  "venvPath": ".",
  "venv": ".venv",
  "include": ["src"],
  "exclude": ["**/__pycache__", ".venv"],
  "reportMissingImports": true,
  "reportMissingTypeStubs": false
}

Or configure via pyproject.toml:

[tool.pyright]
pythonVersion = "3.12"
venvPath = "."
venv = ".venv"
include = ["src"]

Strictness Levels

Pyright has three built-in strictness settings:

off (default): Minimal checking. Only reports syntax errors and obvious issues.

basic: Standard checking. Catches type mismatches, undefined attributes, missing imports, and similar errors.

strict: Maximum checking. Adds:

For a new project, start with basic and migrate to strict over time:

{
  "typeCheckingMode": "basic"
}

Or per-file in Python using # pyright: strict:

# pyright: strict
from typing import Optional

def greet(name: str) -> str:  # annotation required in strict mode
    return f"Hello, {name}"

Common Type Errors and Fixes

Missing return type annotation (strict mode):

# Error: Return type is unknown
def process(data: list[str]):
    return [s.upper() for s in data]

# Fix:
def process(data: list[str]) -> list[str]:
    return [s.upper() for s in data]

Optional not handled:

import os

# Error: "str | None" is not assignable to "str"
path: str = os.environ.get("PATH")

# Fix 1: assert not None
path = os.environ.get("PATH")
assert path is not None

# Fix 2: provide default
path = os.environ.get("PATH", "/usr/bin")

# Fix 3: use Optional
from typing import Optional
path: Optional[str] = os.environ.get("PATH")

TypedDict usage:

from typing import TypedDict

class UserConfig(TypedDict):
    name: str
    email: str
    age: int

def process_user(config: UserConfig) -> None:
    print(config["name"])

# Error: missing required key
bad_config: UserConfig = {"name": "Alice"}  # missing "email" and "age"

Union type narrowing:

def handle(value: str | int) -> str:
    # Error: int doesn't have .upper()
    return value.upper()

# Fix: narrow the type first
def handle(value: str | int) -> str:
    if isinstance(value, str):
        return value.upper()
    return str(value)

Protocol usage:

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None: ...

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

class Square:
    def draw(self) -> None:
        print("Drawing square")

def render(shape: Drawable) -> None:
    shape.draw()

# Works — Circle and Square satisfy Drawable protocol
render(Circle())
render(Square())

Pyright in VS Code (Pylance)

If you use the Python extension for VS Code, Pylance is powered by Pyright. Your pyrightconfig.json is respected automatically.

Configure Pylance's type checking mode in VS Code settings:

{
  "python.analysis.typeCheckingMode": "basic"
}

Settings: off, basic, standard, or strict.

Pylance adds hover types, Go to Definition, and Find References on top of Pyright's type checking.

CI Integration

GitHub Actions:

- name: Type check
  run: |
    pip install pyright
    pyright src/

Pre-commit hook:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/RobertCraigie/pyright-python
    rev: v1.1.390
    hooks:
      - id: pyright

Exit codes: Pyright exits with 0 (success) or 1 (errors found). Use this to fail CI on type errors.

Pyright vs. mypy Feature Comparison

Feature Pyright mypy
Speed Fast Slower on large codebases
Incremental checking Yes Yes (with cache)
VS Code integration Native (Pylance) Via mypy plugin
Strict mode More aggressive Less aggressive
TypedDict Excellent Good
dataclasses Excellent Good
Protocols Full support Full support
Plugins Not supported Plugin ecosystem
Configuration pyrightconfig.json / pyproject.toml mypy.ini / pyproject.toml
Python version Ships via pip/npm Ships via pip

mypy's plugin system is its unique advantage — some third-party libraries (Django, SQLAlchemy) provide mypy plugins for accurate type inference that Pyright can't replicate without vendor support.

Gradual Adoption

You don't need to type-annotate everything at once. Pyright works with partially-typed code:

  1. Run pyright on existing code — errors will appear
  2. Add # type: ignore comments to suppress false positives in third-party code
  3. Add type annotations to new code you write
  4. Fix existing annotations module by module

Per-file suppression:

# pyright: ignore[reportMissingImports]
import untyped_library

Pyright is a pragmatic choice for Python projects: faster than mypy, excellent VS Code integration, and aggressive enough in strict mode to catch real bugs while remaining practical in basic mode for existing codebases.