ariya.io About Collections Archives

TypeScript 2.0 and Strict Null Checking

3 min read

The most recent TypeScript 2.0 includes the ability to treat every type as non-nullable. This is powerful, as ignoring null often leads to latent problems. This post enumerates common type errors related to strict null checking and how they can be remedied.

In the pull request that implements non-nullable types, Anders Hejlsberg (you may know him from Turbo Pascal, Delphi, and C# as well) explained that:

In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any.

Even better, the type checking also takes into account the control flow, as elaborated in his other pull request.

Now, you may already take care of the null problem by incorporating the checks manually at various places. By migrating to TypeScript 2.0, you will enjoy the additional null checking offered by its compiler. As the migration happens, the compiler will start to complain about many things, some of which are described here.

Not assignable to parameter of type ‘never’

The most common reason for this error is because there is no more type widening. Here is an example code that triggers the issue. Imagine that there are two compartments in your lunch box and you have to fill them with your choice of food, with its name and calories:

function bad() {
    const lunchBox = [];
    lunchBox.push(new Sandwich('Tuna', 350));
    lunchBox.push(new Fruit('Banana', 105));
}

which results in something like:

error TS2345: Argument of type 'Fruit' is not assignable to parameter of type 'never'.

The array lunchBox does not have any type information, so it is set to never. As soon as you try to insert an item into the array, the type conflict occurs (never vs Fruit).

Once the problem like this is identified, the fix is rather straightforward: include the type information accordingly. The following snippet demonstrates the solution.

function good() {
    const lunchBox: Food[] = [];
    lunchBox.push(new Sandwich('Tuna', 350));
    lunchBox.push(new Fruit('Banana', 105));
}

Argument of type ‘null’ is not assignable to…

This error is very similar:

error TS2345: Argument of type 'null' is not assignable to parameter of type 'Food'.

and it is the result of the following code:

function bad() {
    const lunchBox: Food[] = [];
    // light lunch today
    lunchBox.push(null);
    lunchBox.push(new Fruit('Banana', 105));
}

Here the values stored in the array lunchBox are supposed to be of the type Food. However, there is a piece of code that tries to insert a null instead (you skip the big meal).

The fix? There are many possibilities. One of them is to modify the type to allow null (as influenced by C# nullable type):

type Nullable<T> = T | null;

which transform the code to look like:

function good() {
    const lunchBox: Nullable<Food>[] = [];
    // light lunch today
    lunchBox.push(null);
    lunchBox.push(new Fruit('Banana', 105));
}

Please note that while the example code above is very clear and the null is spotted right away, it is not always the case with a large function with complex code paths.

Object is possibly ‘null’

Ha, this is the whole point of strict null checks after all!

error TS2531: Object is possibly 'null'

The above error is produced by the following code fragment. The TypeScript compiler conveniently warns us that accessing a property of a null value is not likely what we want. Fixing this issue is left as an exercise for the reader.

function bad(lunchBox: Nullable<Food>[]) {
    const total = lunchBox.reduce((cal, item) => cal + item.calories, 0);
    console.log('Total calories:', total);
}

How do you like this new feature of TypeScript? Share your experience!

Related posts:

♡ this article? Explore more, check the archives, or follow me Twitter.

Share this on Twitter Facebook Google+

comments powered by Disqus