Narrowing arrow types with Array.filter and TypeScript
When dealing with heterogeneous arrays in TypeScript, I frequently want to use list.filter(...)
to extract an array of all one type. However without extra effort, TypeScript will implicitly type the result of that filtering the same as the input.
For example:
Notice how numbers
and strings
are still considered heterogeneous by TypeScript, even though we know they’re not. It turns out Array.filter
is a generic and can accept a type to narrow down to. Here’s how:
With this approach, reallyJustNumbers
and reallyJustStrings
are homogeneous arrays, which makes it easier to work with the items in them.
The key to this approach is two parts:
- Using
filter<type>
to specify the type we’re narrowing down to. - Defining the filter function as a user defined type guard using
(thing): thing is number
.
When we define the function’s return type as thing is number
we’re telling TypeScript that the returned value will be a boolean that indicates whether or not the parameter thing
is of type number
. The logic within our filter function hasn’t changed — it’s just that we’ve given the compiler the information it needs to know that the filter narrows the input type down to just numbers.
User defined type guards are basically awesome. You can read more about them in my article on type guards and user input validation: