Every TypeScript strict flag explained: what each catches, why it matters, and the migration path from loose to strict.
Every TypeScript strict flag explained: what each catches, why it matters, and the migration path from loose to strict.
BeforeMerge offers hundreds of code review rules, guides, and detection patterns to help your team ship better code.
The strict flag in tsconfig.json enables a family of stricter type-checking options. Each catches a different class of bugs.
{
"compilerOptions": {
"strict": true
}
}This is equivalent to enabling all of the following flags individually.
Makes null and undefined their own types instead of being assignable to everything.
// Without: compiles fine, crashes at runtime
const el = document.getElementById("app"); // HTMLElement | null
el.textContent = "hello"; // no error, but runtime crash if null
// With: forces null check
const el = document.getElementById("app");
if (el) el.textContent = "hello"; // safeImpact: High. This is the single most valuable strict flag.
Errors when TypeScript cannot infer a type and falls back to any.
// Error: Parameter 'x' implicitly has an 'any' type
function double(x) { return x * 2; }
// Fix: add type annotation
function double(x: number) { return x * 2; }Enforces contravariant parameter checking for function types.
type Handler = (event: MouseEvent) => void;
// Error: Event is not assignable to MouseEvent
const handler: Handler = (event: Event) => { };Type-checks bind, call, and apply calls.
function greet(name: string) { return `Hello, ${name}`; }
greet.call(null, 42); // Error: number is not assignable to stringClass properties must be initialized in the constructor or with a default.
class User {
name: string; // Error: not initialized
email: string = ""; // OK
age: string;
constructor() {
this.age = "25"; // OK: initialized in constructor
}
}Use the definite assignment assertion ! only when you're sure:
name!: string; // "trust me, this will be set"Errors when this has an implicit any type.
// Error: 'this' implicitly has type 'any'
function getName() { return this.name; }
// Fix: declare this parameter
function getName(this: { name: string }) { return this.name; }Emits "use strict" in every output file and parses in strict mode.
Types catch clause variables as unknown instead of any.
try { /* ... */ } catch (e) {
// e is unknown — must narrow before using
if (e instanceof Error) console.log(e.message);
}"strict": falsestrictNullChecks first (biggest impact, most errors)noImplicitAny"strict": true and remove individual flagsTip: Use // @ts-expect-error sparingly as a migration aid, with a TODO comment to fix later.