The Honest Argument
I'm not going to tell you TypeScript prevents all bugs. It doesn't. I'm going to tell you it prevents the most expensive class of bugs, the ones that surface in production at 2 AM because a property was renamed on the backend and nobody updated the three places it was used on the frontend.
The Bugs TypeScript Actually Prevents
1. Shape mismatches from API changes
// Before TypeScript: found in production
const price = product.price_usd; // backend renamed to `priceUsd` - silent undefined
// With TypeScript: caught at compile time
interface Product {
priceUsd: number; // rename here breaks all callers immediately
}
2. Non-exhaustive switch cases
type Status = "active" | "inactive" | "suspended";
function getLabel(status: Status): string {
switch (status) {
case "active":
return "Active";
case "inactive":
return "Inactive";
// TypeScript errors: "suspended" is not handled
// Without TS: returns undefined silently
}
}
3. Null reference errors
// JavaScript: crashes if user is null
console.log(user.profile.avatar);
// TypeScript: forces you to handle the null case
const avatar = user?.profile?.avatar ?? "/default.png";
The Refactoring Multiplier
The biggest TypeScript benefit isn't bug prevention, it's making large refactors safe.
Rename a prop, change a function signature, restructure a data model. TypeScript tells you every call site that needs updating before you run a single test.
Without TypeScript, large refactors require:
- Exhaustive grep searches
- Manual QA across every affected screen
- Fear that something was missed
With TypeScript, the compiler does the audit. You know when you're done.
Practical Setup for Next.js Projects
The tsconfig I use for every new project:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
strict: true is non-negotiable. The extra flags catch additional real-world issues:
noUncheckedIndexedAccess:arr[0]returnsT | undefined, notTexactOptionalPropertyTypes: differentiates absent vs. explicitlyundefined
The "It Slows Down Development" Myth
TypeScript does slow you down, for the first two hours of a project. After that, it speeds you up, because:
- Autocomplete is accurate (no more guessing object shapes)
- The compiler catches errors before you Alt+Tab to your browser
- Documentation is embedded in types (no need to Google function signatures)
The teams I've seen reject TypeScript are usually the same teams spending
two hours per sprint tracking down Cannot read properties of undefined errors.
Start Strict, Stay Strict
The worst TypeScript is strict: false with // @ts-ignore peppered everywhere.
That's the worst of both worlds: no safety, added friction.
The best TypeScript is strict typing from day one, colocated types, and a culture
where any is a code review trigger, not a shortcut.
If you're on a new project today: start with strict: true. You'll thank yourself
at the six-month mark.