Enabling strictNullChecks in TypeScript: A Practical Migration Guide
Learn how TypeScript's strictNullChecks flag turns null and undefined into distinct types, forces explicit checks, and how to adopt it safely in an existing project.
10 Sept 2026, 05:20 UTC

Why strictNullChecks matters
When you start a new TypeScript project, the compiler is permissive by default: it lets you read properties on values that might be null or undefined without warning. At runtime, those accesses throw errors that are hard to trace. Enabling the strictNullChecks flag changes the type system so that null and undefined are distinct types, and the compiler forces you to handle them explicitly before accessing properties.
How the compiler treats null and undefined
With strictNullChecks off, a type like string | null is still assignable to string in many positions, so the compiler assumes the value is safe to use. Turning the flag on removes that assumption: string | null is no longer a subtype of string. Any attempt to read a property such as .length or call a method triggers a compile‑time error unless you first narrow the type.
Migration strategy for an existing codebase
Enabling the flag globally can surface many errors at once. A smoother approach is to adopt it incrementally:
- Add
"strictNullChecks": trueto yourtsconfig.json. - Run the build. The compiler will list every location where a nullable value is used without a check.
- Fix the errors file by file, or temporarily suppress them with
// @ts-nocheckon a per‑file basis while you work. - When you need a quick escape and are certain a value is not null, use the non‑null assertion operator (
value!)—but treat it as a temporary measure.
Worked example: fixing a property access
Consider a utility that logs the length of a string that may be null:
function logLength(value: string | null) {
return value.length; // Error: Object is possibly 'null'.
}
With strictNullChecks enabled, the compiler reports:
error TS2531: Object is possibly 'null'.
You can resolve it by narrowing the type:
function logLength(value: string | null) {
if (value === null) {
return 0;
}
return value.length;
}
Alternatively, if you are confident the caller never passes null, you can assert:
function logLength(value: string | null) {
return value!.length; // non‑null assertion
}
The assertion silences the error, but you should add a comment or test to justify the assumption.
Trade‑offs and limitations
- Library typings: Many third‑party packages ship declaration files that were written without null‑safety in mind. After enabling the flag, you may see errors in
node_modules. Solutions include upgrading the package, submitting a pull request to fix its types, or declaring a local augmentation that adds| nullwhere appropriate. - Verbosity: Explicit null checks can increase boilerplate, especially in code that frequently deals with optional values. Pattern‑matching utilities or helper functions (e.g., a
nonNullpredicate) can reduce repetition. - Interaction with other strict flags:
strictNullChecksworks alongside options likestrictFunctionTypesandstrictPropertyInitialization. Enabling them together may reveal additional issues, such as callback parameters being inferred as nullable.
Actionable closing steps
- Add or set
"strictNullChecks": truein the compiler options of yourtsconfig.json. - Run
tsc --noEmitto see the full error list without producing output. - Address the errors in order of frequency: start with property accesses, then move to function calls and return statements.
- For each file you modify, run the build again to confirm the error is resolved before moving on.
- Once the build passes, consider enabling the flag in your CI pipeline to prevent regressions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.