You should use the Nullish type

Rob Bertram
2 min readMar 18, 2022

TypeScript opens the doors for enforcing good patterns in your code. Before jumping into the interesting stuff, we should be clear that the problem we’re trying to solve is related to the famous “billion dollar mistake” — in other words, using null in a language. By using null, you open the doors to null pointer exceptions (and equivalent errors). Instead, it would be better to define a variable as optional and allow the type system to force us to deal with the “null” case.

In JavaScript, this linguistic design flaw is made worst by having both undefined and null. While you can read about distinctions between the two, I argue that none of the benefits of these distinctions outweigh the cost of potential bugs that arise because we now have the possibility of both null and undefined related errors to deal with.

So the TLDR of this post is that we should (for all practical purposes) do away with the distinction in our code and treat any optional value as potentially null and undefined instead of just one or the other. Collapsing this distinction forces us to consistently use nullish operators/checks in our code which is more resilient to unnecessary bugs.

For a long time, I wanted my team to use a type we defined as Nullable (which is commonly defined by many teams. Nullable looks like this:

type Nullable<T> = T | null

Our idea was that if we could consistently use Nullable, we could more reliably infer that our types would either have a value or be null and we would just never use undefined. This works really well until you begin interacting with npm packages that have undefined as a valid value. Additionally, other TypeScript developers that contribute to our project can pretty easily add optional parameters or other sources of undefined without it always being noticed during code review.

As mentioned in the intro, Nullish is a better way to deal with these scenarios because it forces us to deal with both null and undefined. Here’s the type definition:

type Nullish<T> = T | null | undefined

So what are some good patterns for handling Nullish? Simple checks can use the nullish coalescing operator:

const getNumber = (n: Nullish<number>) => n ?? 0

More complex Nullish handling can be used with a pattern matching library like ts-pattern (One of my favorites)

const getNumber = (n: Nullish<number>): number => {
return match(n)
.with(__.nullish, () => 0) // nullish case
.otherwise((v) => v);
};

In TypeScript’s strict mode, we may need to use a type predicate with a when statement:

const getNumber = (n: Nullish<number>): number => {
return match(n)
.when((v): v is number => v != null, (v) => v)
.otherwise(() => 0); // nullish case
};
Unlisted

--

--

Rob Bertram

“A language that doesn’t affect the way you think about programming is not worth knowing.”