"Null is its own type. So is undefined. They don't sneak into other types unless you let them."
What it changes
Without strictNullChecks, null and undefined are assignable to every type. A string variable can secretly hold null. A function returning User can secretly return null. The type system says 'string' but the reality says 'string-or-null,' and the discrepancy hides every NullPointerException.
With the flag on, null and undefined are their own types. You must include them explicitly in any union that allows them. string | null accepts null; string doesn't. The type system finally tells the truth.
The cascade of fixes
Turning on strictNullChecks on a legacy codebase exposes every place that silently allowed null. The fixes fall into categories:
- Make the type explicit:
string→string | null. - Narrow before use:
if (x !== null) { ... use x as string ... }. - Use the non-null assertion
!when you know better than the compiler (sparingly). - Refactor to remove the nullability entirely.
strictNullChecks is the second-biggest impact strict flag after noImplicitAny. Combined, those two flags catch the vast majority of latent type unsafety in real codebases.