Strict mode in TypeScript isn't one setting — it's a bundle of flags including strictNullChecks, noImplicitAny, and strictFunctionTypes, among others. We inherited a 40,000-line client codebase running with strict mode off and spent three weeks turning it on. Here's what that actually cost us, and what it bought us.

What broke immediately

strictNullChecks was, by far, the most disruptive single flag. It surfaced over 600 places where the code assumed a value existed when TypeScript couldn't actually guarantee that — optional API response fields accessed without a check, array .find() results used without confirming they weren't undefined, and DOM queries assumed to always succeed.

// Before strict mode — compiles fine, crashes at runtime
const user = users.find(u => u.id === targetId);
console.log(user.name); // user could be undefined

// After — TypeScript forces you to handle it
const user = users.find(u => u.id === targetId);
if (user) {
  console.log(user.name);
}

The bugs it caught were real

Of those 600+ null-check errors, we estimate roughly 40 represented genuine latent bugs — code paths that would crash in production under specific, rare conditions nobody had hit yet in testing. That number alone justified the migration for us. These weren't hypothetical type-safety improvements; they were incidents that hadn't happened yet.

What we'd do differently

Key takeaway

Strict mode is worth it for any codebase with a lifespan longer than a few months, but treat the migration as a real project with its own timeline and priority order — not a config flag you flip on a Friday afternoon.

Three weeks of focused work, on a 40k-line codebase, for roughly 40 real bugs caught before production and a measurably lower rate of null-reference errors since. For us, the math clearly favored making the switch — and every new project since starts with strict mode on from day one.