Claude
Skills
Sign in
Back

pyright-type-checker

Included with Lifetime
$97 forever

Pyright fast Python type checker from Microsoft with VS Code integration and strict type checking modes

General

What this skill does

# Pyright - Fast Python Type Checker

---
progressive_disclosure:
  entry_point:
    summary: "Fast Python type checker from Microsoft with VS Code integration and strict modes"
    when_to_use:
      - "When needing faster type checking than mypy"
      - "When using VS Code (Pylance)"
      - "When requiring stricter type checking"
      - "When migrating from mypy"
    quick_start:
      - "npm install -g pyright"
      - "Create pyrightconfig.json"
      - "pyright ."
  token_estimate:
    entry: 65-80
    full: 3500-4500
---

## Installation

### Node.js (Recommended)
```bash
# Global installation
npm install -g pyright

# Per-project installation
npm install --save-dev pyright

# Verify installation
pyright --version
```

### VS Code (Pylance)
Pyright powers Pylance extension:
```bash
# Install Pylance extension (includes pyright)
code --install-extension ms-python.vscode-pylance
```

### pip Installation
```bash
# Community wrapper
pip install pyright

# Note: Still requires Node.js runtime
```

## Configuration

### pyrightconfig.json
```json
{
  "include": [
    "src"
  ],
  "exclude": [
    "**/node_modules",
    "**/__pycache__",
    ".venv"
  ],
  "typeCheckingMode": "basic",
  "pythonVersion": "3.11",
  "pythonPlatform": "Linux",
  "reportMissingImports": true,
  "reportMissingTypeStubs": false,
  "strictListInference": true,
  "strictDictionaryInference": true,
  "strictSetInference": true
}
```

### Type Checking Modes

**Basic Mode** (Default):
```json
{
  "typeCheckingMode": "basic",
  "reportUnusedImport": "warning",
  "reportUnusedVariable": "warning"
}
```

**Standard Mode**:
```json
{
  "typeCheckingMode": "standard",
  "reportUnknownParameterType": "error",
  "reportUnknownArgumentType": "error",
  "reportUnknownVariableType": "error"
}
```

**Strict Mode** (Maximum type safety):
```json
{
  "typeCheckingMode": "strict",
  "reportPrivateUsage": "error",
  "reportConstantRedefinition": "error",
  "reportIncompatibleMethodOverride": "error",
  "reportIncompatibleVariableOverride": "error",
  "reportUnnecessaryIsInstance": "warning",
  "reportUnnecessaryCast": "warning"
}
```

### Per-File Configuration
```python
# pyright: strict
"""Strict type checking for this file."""

# pyright: basic
"""Basic type checking."""

# pyright: reportGeneralTypeIssues=false
"""Disable specific diagnostics."""
```

## VS Code Integration

### settings.json
```json
{
  "python.languageServer": "Pylance",
  "python.analysis.typeCheckingMode": "basic",
  "python.analysis.diagnosticMode": "workspace",
  "python.analysis.autoImportCompletions": true,
  "python.analysis.inlayHints.functionReturnTypes": true,
  "python.analysis.inlayHints.variableTypes": true,
  "python.analysis.completeFunctionParens": true
}
```

### Workspace Configuration
```json
{
  "python.analysis.extraPaths": [
    "./src",
    "./lib"
  ],
  "python.analysis.stubPath": "./typings",
  "python.analysis.diagnosticSeverityOverrides": {
    "reportUnusedImport": "warning",
    "reportUnusedVariable": "warning",
    "reportGeneralTypeIssues": "error"
  }
}
```

## Type Checking Features

### Type Narrowing
```python
from typing import Union

def process(value: Union[str, int]) -> str:
    # Pyright narrows type based on isinstance
    if isinstance(value, str):
        return value.upper()  # value is str here
    else:
        return str(value)  # value is int here

# Type guards
from typing import TypeGuard

def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
    return all(isinstance(x, str) for x in val)

def process_list(items: list[object]) -> None:
    if is_str_list(items):
        # items is list[str] here
        print(", ".join(items))
```

### Protocol Support
```python
from typing import Protocol

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

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

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

# Works with structural typing
render(Circle())  # ✓ No explicit inheritance needed
```

### TypedDict
```python
from typing import TypedDict, NotRequired

class User(TypedDict):
    name: str
    age: int
    email: NotRequired[str]  # Optional in Python 3.11+

def create_user(data: User) -> None:
    print(data["name"])  # ✓ Type-safe
    # print(data["missing"])  # ✗ Error

user: User = {
    "name": "Alice",
    "age": 30
}  # ✓ email is optional
```

### Literal Types
```python
from typing import Literal

Mode = Literal["read", "write", "append"]

def open_file(mode: Mode) -> None:
    ...

open_file("read")    # ✓
open_file("delete")  # ✗ Error
```

## Advanced Features

### Variance and Generics
```python
from typing import TypeVar, Generic, Sequence

T_co = TypeVar("T_co", covariant=True)
T_contra = TypeVar("T_contra", contravariant=True)

class Reader(Generic[T_co]):
    def read(self) -> T_co: ...

class Writer(Generic[T_contra]):
    def write(self, item: T_contra) -> None: ...

# Covariance: Reader[Dog] is subtype of Reader[Animal]
# Contravariance: Writer[Animal] is subtype of Writer[Dog]
```

### ParamSpec
```python
from typing import ParamSpec, TypeVar, Callable

P = ParamSpec("P")
R = TypeVar("R")

def add_logging(f: Callable[P, R]) -> Callable[P, R]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        print(f"Calling {f.__name__}")
        return f(*args, **kwargs)
    return wrapper

@add_logging
def greet(name: str, age: int) -> str:
    return f"Hello {name}, {age}"

# Type-safe: greet("Alice", 30)
```

### Type Aliases
```python
from typing import TypeAlias

# Simple alias
UserId: TypeAlias = int
Username: TypeAlias = str

# Generic alias
from collections.abc import Sequence
Vector: TypeAlias = Sequence[float]

# Complex alias
JSON: TypeAlias = dict[str, "JSON"] | list["JSON"] | str | int | float | bool | None
```

## CI/CD Integration

### GitHub Actions
```yaml
name: Type Check

on: [push, pull_request]

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

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install pyright
        run: npm install -g pyright

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run pyright
        run: pyright
```

### Pre-commit Hook
```yaml
# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: pyright
        name: pyright
        entry: pyright
        language: node
        types: [python]
        pass_filenames: false
        additional_dependencies: ['[email protected]']
```

### Makefile
```makefile
.PHONY: typecheck typecheck-strict

typecheck:
	pyright

typecheck-strict:
	pyright --level strict

typecheck-watch:
	pyright --watch

typecheck-stats:
	pyright --stats
```

## Migration from mypy

### Configuration Mapping
```json
{
  "// mypy: disallow_untyped_defs": "reportUntypedFunctionDecorator",
  "// mypy: disallow_any_generics": "reportMissingTypeArgument",
  "// mypy: warn_return_any": "reportUnknownArgumentType",
  "// mypy: strict_equality": "reportUnnecessaryComparison",
  "// mypy: warn_unused_ignores": "reportUnnecessaryTypeIgnoreComment"
}
```

### Comment Syntax
```python
# mypy: ignore-errors
# ↓ pyright equivalent
# pyright: reportGeneralTypeIssues=false

# type: ignore
# ↓ pyright equivalent
# pyright: ignore

# type: ignore[error-code]
# ↓ pyright equivalent
# pyright: ignore[reportGeneralTypeIssues]
```

### Gradual Migration
```json
{
  "typeCheckingMode": "basic",
  "include": ["src/new_module"],
  "exclude": ["src/legacy"],
  "reportMissingImports": true,
  "reportMissingTypeStubs": false
}
```

## Performance Optimization

### Baseline Performance
```bash
# Create performance baseline
pyright --stats --createstub

# Compare after changes
pyright --stats
```

#

Related in General