The compile-time gate that lint can't do
Type checking is what catches bugs lint cannot — wrong-type arguments, missing fields, unhandled None / null, mismatches between API contracts. It runs at the boundary between 'static analysis' and 'simulated execution' — it walks every code path mentally so you don't have to.
The major checkers
- Python — mypy: gradual typing, the original. Reads PEP 484 type hints. Strict mode is recommended (
--strict). - Python — pyright: Microsoft's. Faster, more accurate inference, powers Pylance in VS Code. Often used alongside ruff.
- TypeScript — tsc:
tsc --noEmitjust type-checks without producing output. The canonical gate. - JavaScript with JSDoc — yes, JSDoc +
// @ts-checkbuys you most of TypeScript's checking without a transpile step.
Type checking in CI
- Make it a separate job (parallel with test, lint).
- Pin the checker version — type errors change between releases.
- Output should be both human-readable and machine-readable when you want annotations on the PR diff.
- For Python, run on the same Python version as production.