The 8 TypeScript Anti-Patterns That Keep Surviving Code Review
TypeScript's value collapses when developers override it with `any`, `as`, and disabled strict checks. Each shortcut saves seconds during authoring but costs minutes — sometimes hours — during debugging and onboarding, and the patterns compound across a team.
Code reviews across three new team members surfaced the same patterns: `any` used to silence type errors, `as` assertions standing in for runtime validation, and optional chaining stretched across entire property chains. Each anti-pattern represents a moment where TypeScript's safety net was deliberately bypassed, leaving the next developer to guess at data shapes and nullability.
Fixes are straightforward but require discipline. Replacing `any` with `unknown` and type guards forces verification before access. Moving null checks to boundary layers — API responses, component props — keeps internal logic working with definite types. Union types replace most enums at zero runtime cost, and a team-wide rule on `interface` versus `type` removes pointless cognitive overhead.
The most damaging pattern is the one that looks harmless: `strict: false` or selectively disabling `strictNullChecks`. It tells the compiler to assume nothing is ever null, which is precisely when runtime crashes slip through. For legacy projects, `@ts-expect-error` annotations plus a TODO list beat leaving strict off indefinitely.
The patterns aren't knowledge gaps — they're time-pressure shortcuts. `any` and `as` are the fastest way to silence a red squiggle, and the cost is deferred to whoever touches the code next.
Optional chaining abuse is really a symptom of unclear ownership over data shapes. When no single layer validates structure, every consumer defensively adds `?.` and the uncertainty propagates.
The enum-versus-union-type debate is less about technical merit and more about whether a team values runtime objects or zero-cost types; most frontend code benefits from the latter.
TypeScript's strict family of flags is a ratchet: turning one off weakens the entire system, but turning them all on forces a level of rigor that catches bugs before they reach production.