What is strictNullChecks?
`strictNullChecks` is a compiler option in TypeScript that enforces more rigorous checking for `null` and `undefined` values, aiming to prevent common runtime errors that arise from unintentionally accessing properties or methods on potentially null or undefined objects.
What is `strictNullChecks`?
By default, TypeScript allows null and undefined to be assigned to any type (e.g., string, number, object) without error. This behavior, inherited from JavaScript, is a common source of bugs where a variable expected to hold a concrete value ends up being null or undefined.
When strictNullChecks is enabled, null and undefined are no longer automatically assignable to other types. Instead, they become their own distinct types (null and undefined), and to assign them to a variable of another type, that type must explicitly include null or undefined in its union (e.g., string | null, number | undefined).
Why is `strictNullChecks` important?
The primary benefit of strictNullChecks is preventing a large class of common runtime errors, such as TypeError: Cannot read properties of null (reading 'x') or TypeError: Cannot read properties of undefined (reading 'y'). By catching these potential issues at compile-time, it significantly improves the reliability and robustness of your TypeScript applications.
It forces developers to explicitly handle cases where a value might be null or undefined, leading to more defensive and predictable code. This clarity also makes the code easier to understand and maintain, as the types accurately reflect the possible states of a variable.
How it works in practice
With strictNullChecks, if you declare a variable as let name: string;, TypeScript will flag an error if you try to assign null or undefined to it. If you intend for a variable to potentially hold null or undefined, you must explicitly declare it as a union type.
// Without strictNullChecks (or if explicitly typed as string | null)
let username: string | null = null;
console.log(username?.toUpperCase()); // Safe navigation operator handles null
// With strictNullChecks enabled
let firstName: string = "Alice";
// firstName = null; // Error: Type 'null' is not assignable to type 'string'.
let lastName: string | null = "Smith";
lastName = null; // OK
// console.log(lastName.length); // Error: Object is possibly 'null'.
if (lastName) {
// Type narrowing: inside this block, lastName is known to be string
console.log(lastName.length); // OK
}
TypeScript's control flow analysis plays a crucial role. When strictNullChecks is enabled, the compiler intelligently narrows types based on conditional checks (e.g., if (value), if (value !== null), if (value !== undefined)), allowing you to safely access properties or call methods on values that have been determined to be non-null/non-undefined within a specific scope.
Enabling `strictNullChecks`
To enable strictNullChecks, you need to set the strictNullChecks option to true in your tsconfig.json file, typically within the compilerOptions section. It is also part of the broader strict compiler option, which enables a suite of recommended strict checking options, including strictNullChecks.
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true, // This enables strictNullChecks along with other strict checks
// Or specifically:
// "strictNullChecks": true,
"skipLibCheck": true
}
}
It is highly recommended to enable strictNullChecks for all new TypeScript projects. For existing projects, migrating can sometimes require some refactoring to explicitly handle null/undefined scenarios, but the long-term benefits in terms of code quality and bug reduction usually outweigh the initial effort.