TypeScript Type-safe Filter Boolean


Here's how to make a type-safe alternative to .filter(Boolean) in TypeScript.

Boolean Filter

In JavaScript, there's a nice little short-hand for filtering non-nulls. If I have a sparse array:

const arr = ['a', undefined, 'b', null, 'c']

I can get rid of the nulls like this:

arr.filter(Boolean).forEach(character => console.log(character.toUpperCase()))

And that will print:

"A"
"B"
"C"

This is because the Boolean constructor is used as the callback and has these properties:

> Boolean(undefined)
false
> Boolean(null)
false
> Boolean('')
false
> Boolean('a')
true

TypeScript Boolean Filter

But in TypeScript, this does not type check. This code:

arr.filter(Boolean).forEach(character => console.log(character.toUpperCase()))

Will yield this error on the dot operator for character.toUpperCase():

'character' is possibly 'null'.(18047)
(parameter) character: string | null

It works. It just doesn't type check. We can tell TypeScript not to care, and it's happy:

arr.filter(Boolean).forEach(character => console.log((character as any).toUpperCase()))

That prints "A" "B" "C". But the solution is yucky.

Type-safe Filter Boolean

What we really need is the equivalent of .filter(Boolean), but type safe. We can get that with this custom function:

function isDefined<T>(value: T | null | undefined): value is NonNullable<T> {
  return value !== null && value !== undefined
}

It uses that nice predicate to type narrow to NonNullable.

Then, to use it:

arr.filter(isDefined).forEach(character => console.log(character.toUpperCase()))

It type checks and is equivalent to .filter(Boolean)! You need a custom function now, but I guess that's the price to pay for TypeScript in this case.