How To Filter Nullable Values From An Array Using TypeScript

May 15, 2022 - 5 minutes

If you’ve dealt with any type of complex data in JavaScript development, it’s almost guaranteed that you’ve used the functional Array methods. These methods are shorter and the more functional alternatives to the traditional implementation, often resolving around using a for-loop and populating an array conditionally.

Using these methods in the correct circumstances and in the appropriate environment can significantly improve the quality and readability of your code. This is especially the case when they’re combined with TypeScript. But while TypeScript excellently supports the Array map function out-of-the-box, the same can’t be said about the Array filter function.

In particular, we’ll be looking at filtering out nullable values from such an array. From the perspective of the developer, TypeScript doesn’t always correctly pick up on the typing when filtering out nullable values using the filter function. Even though using operators like !! or the Boolean constructor guarantees us to have no nullable values anymore, TypeScript still assumes otherwise.

interface Array<T> {
  // ...
  filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];

To understand why this happens, we would have to take a look at the TypeScript type definition of the filter function. The main thing to notice is that the predicate function, which is the callback that you define as the first function argument, is responsible for determining the type of values in the resulting array. This means that if the operation in the predicate doesn’t concretely result in a new type, the filter function will assume that the array of objects before and after the function call has remained the same.

This is where most of the issues arise. Developers often define the predicate function inline, which means they’re leaving it all in the hands of TypeScript to derive the proper typings. Together with that, JavaScript has some non-conventional ways to check for nullable values. Think of the !! operator or the Boolean constructor approach that we mentioned earlier. While we as developers know these approaches work, they aren’t as clear-cut for TypeScript. This causes a mismatch in typing.

This article will cover different ways to sort out the typing when filtering nullable values from an array using TypeScript. These include inline type guarding, type casting, and a general utility function. Using this knowledge, you’ll be able to make your filter function calls properly synchronize with TypeScript and enjoy the type derivation that you deserve.

Inline Type Guarding

In TypeScript, there exists the concept of type guarding. Basically, at the function definition level, you type the return value of a function as a type predicate rather than a concrete type. This indicates to TypeScript that whenever the function evaluates to a truthy value, the object is the same type as the result of the type predicate.

But instead of doing this on the function definition level, you’re also able to do this inline onto a callback. By leveraging this mechanic, you can type the return value of the filter function callback using a type predicate of your desired type. Then you can use your preferred way of checking for a nullable value and TypeScript will automatically infer the non-nullable typing after the filter call.

type SomeObject = { /* */ };

const arrayWithNullableValues: Array<SomeObject | null | undefined> = [/* */];

const arrayNonNullable = arrayWithNullableValues.filter((value): value is SomeObject => !!value);

Type Casting

Another approach to getting proper types onto a nullable filtered array is making use of type casting. Type casting is not a TypeScript specific concept, but exists in almost all type systems or typed programming languages. It’s a mechanic where the developer can forcefully tell the type system to consider a value to be a certain type. While not recommended, there are scenarios where they can be useful when developers are entirely sure about the results.

As the filter function only accepts predicate functions, it’s impossible to affect the type of the resulting array by performing type casting inside the callback. Instead, it has to be performed on the variable level, after the filter function is applied. As mentioned, with as Array<T> we’re telling TypeScript to put aside everything they know about the array and consider it an array of type T going forward.

type SomeObject = { /* */ };

const arrayWithNullableValues: Array<SomeObject | null | undefined> = [/* */];

const arrayNonNullable = arrayWithNullableValues.filter(value => !!value) as Array<SomeObject>;

General Utility Function

Lastly, one could also create a utility function which would do the filtering and make sure that the typing is done properly. Similar to the first approach, this makes use of type guarding. However, the difference is that the typing is defined with a standalone function rather than inline in the filter function callback.

The typing itself isn’t different from the first approach that we looked into. Basically, we’re defining the return type of the function as a type predicate, indicating to TypeScript that the passed value is a non-nullable value of the utility function that returns a true value.

You can even make this utility function a generic one that can be reused for filtering non-nullable values for any object or value. To do so, you’ll have to change the typing definition of the function to make use of a generic type. Besides that, everything is the same and now you have a general utility function that will filter non-nullable values properly in TypeScript.

function isNonNullable<TValue>(value: TValue | undefined | null): value is TValue {
	return value !== null && value !== undefined; // Can also be `!!value`.

type SomeObject = { /* */ };

const arrayWithNullableValues: Array<SomeObject | null | undefined> = [/* */];

const arrayNonNullable = arrayWithNullableValues.filter(isNonNullable);

Final Thoughts

No matter whether you’re using React, Node, or other forms of JavaScript library, a function that you’ll likely have used a lot is the Array filter function. A common use case, especially in the realm of JavaScript development, is to filter out nullable values from an array. However, if you use this in combination with TypeScript, the typing doesn’t always end up as expected.

To solve this, this article went over 3 ways to sort out the typing when filtering out nullable values from an array using TypeScript. This includes applying inline type guarding onto the filter function predicate, type casting of the resulting array, and using a general utility function that is type guarded. Using these methods, you’ll be able to filter nullable values from an array and get the appropriate typings.

After graduation, my career is entirely centered around learning and improving as a developer. I’ve began working full time as a React developer and I’ll be blogging about everything that I encounter and learn during this journey. This will range from improving communicational skills in a technical environment, becoming a better developer, improving technical skills in React and JavaScript, and discussing career related topics. In all of my posts, the focus will be on my personal experiences, learnings, difficulties, solutions (if present), and also flaws.

If you’re either interested in these topics, more personalised technical stories, or the perspective of a learning developer, you can follow me either on Twitter or at Dev to stay up to date with my blogposts. I’m always learning, so stay tuned for more stories! 🎉