Type checkers verify that the values flowing through your program match the types you declared, before the program runs. In dynamic languages, type-checking has been the biggest productivity shift of the last decade — TypeScript reshaped JavaScript, mypy and Sorbet did the same for Python and Ruby. The benefit isn't catching weird bugs; it's making large refactors safe and IDE intelligence usable.
← Back to TestingRename a property used in 1,000 places. Change a function signature. Move a class. The type checker tells you every call site that no longer compiles. Without it, you're greping for usages and praying. This alone justifies the migration cost in mid-to-large codebases.
Autocomplete, jump-to-definition, find-all-references, inline docs, parameter hints — all driven by types. In a fully-typed JS codebase, the IDE behaves like a Java IDE in 2010. The productivity uplift is enormous.
Null/undefined handling, mismatched arguments, missing fields, typos in property names, accidental implicit coercions. The kind of bug that, in the dynamically-typed world, only surfaces at runtime — usually in the customer's session, not yours.
Type signatures describe what a function takes and returns without needing a comment. New contributors can read the API of a module by reading the types. Comments lie; types compile.
Microsoft's open-source superset of JavaScript with structural typing and gradual adoption. Effectively the default for new JS projects in 2026 — even teams who write .js usually use TypeScript via JSDoc annotations to get IDE support. Strict mode (strict: true) catches most of what's worth catching.
Worth knowing: generics, mapped types, conditional types, discriminated unions, satisfies. The type system is expressive enough to encode real domain constraints.
Python type hints went stable in 3.5 (2015) and have grown rapidly. mypy is the original checker; Pyright (Microsoft, behind Pylance in VSCode) is faster and stricter. Most large Python codebases use Pyright in IDEs and mypy in CI, or just Pyright everywhere now.
PEP 484, 526, 612, 695 added the modern syntax. from __future__ import annotations helps with forward references. Tools like pydantic use the type hints at runtime for validation.
Sorbet from Stripe — gradual typing with the strongest large-codebase track record in Ruby. RBS is the official Ruby community type system, with Steep as the type checker. Less universally adopted than TypeScript or mypy, but powerful when used.
Type-checkers that work on PHP's type hints plus inferred types. PHPStan and Psalm both ladder up through "levels" — start at level 1, increase strictness as you fix issues. Standard equipment in serious PHP shops.
Facebook's earlier alternative to TypeScript. Mostly displaced; a small number of legacy projects still use it.
Java, C#, Go, Rust, Kotlin, Swift — type checking is the compiler. Strictness varies (Rust and Kotlin have nullability in the type system; Java has it via annotations and tools like NullAway, ErrorProne). The disciplines are the same — watch nullability, leverage generics, don't reach for Object / any / interface{} when a real type fits.
For greenfield projects, turn on strictness from day one. strict: true in TypeScript, --strict in mypy, Pyright's strict mode. Adding strictness later is much harder than living with it from the start.
Type the new code. Type the modules under active change. Don't migrate a 100k-line codebase to types in one PR — the diff is unreviewable.
Tools: TypeScript's allowJs + checkJs + JSDoc, mypy's per-module strictness, PHPStan's levels. They all let typed and untyped coexist.
any in TypeScript, Any in Python, T.untyped in Sorbet. Useful in tight spots; corrosive when widespread. The first any you write is fine; the hundredth becomes a tradition. Lint rules to flag explicit-any on new code save the codebase.
When typed code calls untyped libraries, write a thin typed wrapper. The boundary becomes the place to validate; the rest of the codebase trusts types. Validation libraries: Zod (TS), pydantic (Python), dry-validation (Ruby).
Types are a layer of cheap defense. They don't replace tests, code review, or judgment. They make the rest of those activities much more productive.