Strict Mode and Compiler Options
Strict Mode and Compiler Options
Strictness settings define how much TypeScript helps you. Strict mode is the best long‑term investment in correctness.
Item 115: Turn On strict
{
"compilerOptions": {
"strict": true
}
}This enables a set of safe defaults. If you can only turn on one flag, make it this.
Why it matters: strict mode catches entire classes of bugs early. The cost of fixing a bug is lowest at compile time, not in production.
Item 116: Know the Most Important Strict Flags
- noImplicitAny: disallow implicit
any - strictNullChecks: make
nullandundefinedexplicit - strictFunctionTypes: safer function variance
- strictBindCallApply: safer
call/apply/bind - strictPropertyInitialization: class fields must initialize
- noImplicitThis:
thismust be typed
Why it matters: these flags target the most common sources of runtime errors in JavaScript—nulls, implicit any, and mis-typed callbacks.
Item 117: Enable noUncheckedIndexedAccess
This makes indexed access safer by adding undefined:
const arr = [1, 2, 3];
const first = arr[0]; // number | undefinedIt forces you to handle missing values explicitly.
Why it matters: production crashes often come from unexpected undefined. This flag makes those cases visible in code review and CI.
Item 118: Use exactOptionalPropertyTypes
interface User {
name: string;
nickname?: string;
}
// With exactOptionalPropertyTypes: true
const user: User = { name: "Alice", nickname: undefined }; // ErrorThis clarifies the difference between “missing” and “explicitly undefined.”
Why it matters: optional properties are frequently used for partial data. This flag prevents subtle bugs when you accidentally set a property to undefined instead of omitting it.
Item 119: Keep useUnknownInCatchVariables
try {
risky();
} catch (err) {
// err is unknown
if (err instanceof Error) {
console.error(err.message);
}
}Why it matters: anything can be thrown in JavaScript. Treating caught errors as unknown forces you to handle non‑Error values safely.
Item 120: Use noImplicitOverride
class Base {
save() {}
}
class Child extends Base {
override save() {}
}This prevents accidental method shadowing.
Why it matters: overrides are a common source of silent bugs—one typo can create a new method instead of overriding the base method.
Item 121: Add noUnusedLocals and noUnusedParameters
These flags keep code clean and signal dead logic early.
Why it matters: unused values often indicate unfinished refactors or logic that never runs—both are risk factors for bugs.
Item 122: Use noFallthroughCasesInSwitch
It prevents accidental switch fall‑through.
Why it matters: switch fall‑through is easy to miss in reviews and can cause subtle behavior changes when new cases are added.
Item 123: Avoid skipLibCheck Unless Necessary
It speeds builds but can hide real issues in dependencies.
Warning
If you turn on skipLibCheck, add a comment explaining why and track it as
tech debt.
Why it matters: type errors in dependencies can leak into your code through unsafe types. Skipping checks can mask real integration issues.
Recommended Strict Config
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"useUnknownInCatchVariables": true,
"noImplicitOverride": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
}
}Key Takeaways
- Enable
strictfor all new projects. - Add
noUncheckedIndexedAccessandexactOptionalPropertyTypesfor extra safety. - Use
useUnknownInCatchVariablesandnoImplicitOverrideto avoid subtle bugs. - Avoid
skipLibCheckunless you have no alternative.
You're ready to write effective, safe, and scalable TypeScript!