strictNullChecks
By default null
and undefined
are assignable to all types in TypeScript e.g.
let foo: number = 123;
foo = null; // Okay
foo = undefined; // Okay
This is modelled after how a lot of people write JavaScript. However like all things TypeScript allows you to be explicit about what can and cannot be assigned a null
or undefined
.
In strict null checking mode, null
and undefined
are different:
let foo = undefined;
foo = null; // NOT Okay
Let say we have a Member
interface:
interface Member {
name: string,
age?: number
}
Not every member will provide their age, so the age
is an optional property. It means the value of age
will probably be undefined
.
undefined
is the root of all evil. It always lead to runtime error. We are always easy to write some code that will probably throw Error
:
getMember()
.then(member: Member => {
const stringifyAge = member.age.toString() // probably throw Cannot read property 'toString' of undefined
})
But in strict null checking mode, it will throw an error at compile time:
getMember()
.then(member: Member => {
const stringifyAge = member.age.toString() // Object is possibly 'undefined'
})
Non-Null Assertion Operator
A new !
post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. For example:
// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
// Throw exception if e is null or invalid entity
}
function processEntity(e?: Entity) {
validateEntity(e);
let a = e.name; // TS ERROR: e may be null.
let b = e!.name; // Assert that e is non-null. This allows you to access name
}
Note that it is just an assertion, and just like type assertions you are responsible for making sure the value is not null. A null assertion is essentially you telling the compiler "I know its not null so let me use it as though its not null".