TypeScript stopped being a "should we adopt it" conversation years ago. In 2026 it's plumbing — defaulted, expected, taken for granted. New JavaScript projects generally start with TypeScript unless someone has a specific reason not to. Library docs assume it. Job listings assume it. Tooling assumes it.
That maturity is mostly good news. It also means the easy productivity wins are behind us, and what's left is the harder discipline of using TypeScript well over years.
TypeScript Is Now Boring Infrastructure
The exciting era — "TypeScript will save your codebase" — is over. The current era is more like electricity: there, useful, expected, occasionally annoying. The most interesting thing about a TypeScript project in 2026 is no longer that it uses TypeScript.
A reasonable baseline tsconfig.json for a new project:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"skipLibCheck": true
}
}
Nothing in that config was controversial when this was published. Five years ago some of these flags were "advanced." Now they're table stakes. Anything looser is a red flag for a codebase that hasn't kept up.
Strictness Is A Team Decision
The team that opts into stricter checks gets more help from the compiler and writes more verbose code. The team that opts out gets less ceremony and more runtime bugs. Neither is wrong; both have a cost.
A useful trade-off table:
| Flag | Cost | Benefit |
|---|---|---|
strict: true |
initial migration pain | catches the entire null-bug class |
noUncheckedIndexedAccess |
every arr[i] becomes T | undefined |
catches gap-in-array bugs |
exactOptionalPropertyTypes |
can't pass undefined to field?: |
enforces the null/undefined distinction |
noImplicitOverride |
must mark overrides explicitly | catches base-class drift |
noPropertyAccessFromIndexSignature |
dot access on dictionaries fails | enforces lookup safety |
Adopt them gradually if migrating; adopt all of them on day one for new projects. The cost is upfront; the benefit compounds.
The Go-Based Compiler Changed The Cost
The Microsoft TypeScript team's port of the compiler to Go (which started shipping previews through 2025) is the biggest practical change of the last few years. Cold builds that used to take 30 seconds take 3. Watch mode is near-instant. CI build steps that were the slowest part of the pipeline have moved to the noise floor.
What this enables in practice: stricter checks become affordable in larger codebases. Pre-commit hooks that run tsc --noEmit become viable. CI fans out across packages without "build time" being the dominant concern. The discipline-vs-friction trade-off shifts in favor of more discipline.
If your team is still on the JavaScript-based compiler in 2026, the Go port is worth the migration. The friction is small; the speedup is real.
Runtime Validators Are Normal Now
Five years ago, schema-first development with zod or its competitors was "an interesting pattern some teams use." In 2026 it's the default for any serious codebase that touches a network. Schemas at every boundary, types inferred from schemas, no more as User lying to the compiler.
The library landscape has consolidated:
- zod — the dominant choice, mature, large ecosystem
- valibot — smaller, faster, similar API
- arktype — type-level inference at the syntax level
- ajv — older but still excellent for JSON Schema compatibility
Pick one, stick with it across the codebase. The standard pattern is schema → infer type → use everywhere. Drift between hand-written types and schema-derived types is a smell.
What Still Hurts
Honest about the parts that haven't gotten better:
- Build times scale poorly past a certain repo size — even with the Go compiler, monorepos still need careful project references and incremental builds.
- Type-level metaprogramming is a tempting overuse pattern; clever types still slow editor responses.
- Bundler/runtime mismatch — types compile but the bundle ships broken because some import resolution detail differed. Less common than it used to be, still happens.
- Library type quality varies —
@types/*packages range from excellent to actively misleading. - The "any escape hatch" is still there. Codebases that rely on it lose most of TypeScript's value.
These aren't going away. They're trade-offs of the language meeting reality.
What Discipline Looks Like Now
For a senior engineer in 2026, "good TypeScript" is less about knowing every advanced feature and more about:
- Knowing which features earn rent in your codebase
- Validating at every boundary with a schema library
- Resisting clever types that the next reader can't follow
- Keeping the compiler happy without
any/asshortcuts - Treating tsconfig strictness as a team decision with documented trade-offs
These aren't skills you learn from the docs. They come from refactoring a few real codebases and noticing what aged well.
Pro Tips
- Migrate to the Go-based compiler. The build-time savings are real.
- Strict by default, including
noUncheckedIndexedAccessandexactOptionalPropertyTypes. - One schema library across the codebase. Mixed validators are friction.
- Audit
any/asusage in code review. Every escape hatch is a small bet against the type system. - Treat type quality as part of code quality. Hover-test your types; if they're unreadable, simplify.
Final Tips
TypeScript in 2026 is mature, fast, and unremarkable. That's the point. The interesting question is no longer "should we use TypeScript" but "how do we use it well over five years without ending up with a clever-types graveyard."
The boring answer: pick strict flags, use schemas at boundaries, write types your future self can read, and let the tooling catch bugs the compiler can see. Save the cleverness for problems the compiler can't.
Good luck — and may your TypeScript stay boring in the best possible way 👊



