TypeScript handles ‘null‘ and ‘undefined‘ values as special types, distinct from other types in the type system. However, by default, TypeScript allows assigning ‘null‘ and ‘undefined‘ to any type, which can lead to some unintended behavior.
To illustrate the basic behavior of ‘null‘ and ‘undefined‘ in TypeScript, consider the following example:
let str: string = "Hello, world!";
str = null; // No error
str = undefined; // No error
In the above example, although the variable ‘str‘ has a type of ‘string‘, TypeScript allows assigning ‘null‘ and ‘undefined‘ to it without throwing any error.
However, TypeScript provides a strict null checking feature, which can be enabled by setting the ‘strictNullChecks‘ flag in the ‘tsconfig.json‘ configuration file or adding the ‘–strictNullChecks‘ flag to the compiler options.
When strict null checks are enabled, TypeScript enforces stricter rules around assignments and checks involving ‘null‘ and ‘undefined‘. Here’s an example demonstrating this behavior:
let str: string = "Hello, world!";
str = null; // Error: Type 'null' is not assignable to type 'string'
str = undefined; // Error: Type 'undefined' is not assignable to type 'string'
Now, to work with strict null checks, you should use union types to explicitly allow ‘null‘ and ‘undefined‘ values:
let str: string | null | undefined = "Hello, world!";
str = null; // No error
str = undefined; // No error
With strict null checks enabled, TypeScript improves type safety and helps eliminate the possibility of runtime errors caused by unintended ‘null‘ or ‘undefined‘ values.
Additionally, TypeScript provides two utility types ‘NonNullable<T>‘ and ‘Required<T>‘ that help in stricter type checking. The ‘NonNullable<T>‘ type removes ‘null‘ and ‘undefined‘ from the given type, while ‘Required<T>‘ makes all properties of the type required and removes ‘undefined‘.
To better understand how TypeScript uses these types, consider the following code snippet:
type Person = {
name: string | null;
age: number | undefined;
}
type NonNullablePerson = NonNullable<Person>; // Error: Property 'age' is optional in type 'Person' but required in type 'Required<Person>'
type RequiredPerson = Required<Person>;
const person: RequiredPerson = {
name: "John",
age: 30
};
person.age = undefined; // Error: Type 'undefined' is not assignable to type 'number'
In conclusion, TypeScript handles ‘null‘ and ‘undefined‘ values as distinct types by default; however, it allows them to be assigned to any type. By enabling strict null checks in TypeScript, the type system will force developers to handle ‘null‘ and ‘undefined‘ values explicitly and improve the type safety of the code.