Skip to main content

TypeScript Array Filter

The TypeScript array filter method is a handy tool for creating new arrays with selected elements, removing unwanted data, and applying detailed logic to your datasets. Thanks to its strong type system, TypeScript keeps your code safe and easy to manage, even with complex data structures. In this article, we'll explore the TypeScript array filter method, covering its syntax, usage, and best practices. Whether you're an experienced developer or new to TypeScript, this guide will help you handle any array filtering tasks with confidence.

Making a New Array with Selected Elements

In TypeScript, the filter method creates a new array with elements that pass a test in the provided function. Here's an example:

const numbers = [1, 2, 3, 4, 5];

const evenNumbers = numbers.filter((num) => num % 2 === 0);

console.log(evenNumbers); // [2, 4]

This code creates a new array, evenNumbers, which only includes the even numbers from the original numbers array. The filter method doesn't modify the original TypeScript array, making it perfect for functional programming approaches where immutability is valued.

The filter callback function takes up to three parameters: the current element, its index, and the array being processed. It should return a boolean value - true keeps the element, false discards it.

TypeScript automatically preserves the typing from the original array to the filtered array, which makes this method both powerful and type-safe.

Filtering an Array of Objects by Property Value

To filter an array of objects based on a property value, access the property within the callback function. For example:

interface User {
id: number;
name: string;
age?: number;
}

const users: User[] = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane', age: 25 },
{ id: 3, name: 'Bob', age: 30 },
];

const usersWithAge = users.filter((user) => user.age !== undefined);

console.log(usersWithAge);
// [
// { id: 2, name: 'Jane', age: 25 },
// { id: 3, name: 'Bob', age: 30 },
// ]

This code filters the users array to keep only objects with a defined age property. The optional parameter (age?) in the interface indicates that this property might not exist on every object.

When filtering objects, you can create complex conditions by combining property checks. The TypeScript typeof operator is often helpful for ensuring the properties exist and are of the expected type before performing operations on them.

Convex allows you to apply similar filtering techniques when working with database queries. For example, you can filter documents based on property values using the complex filters in Convex helper.

Using Conditional Logic for Filtering

You can use logical operators like &&, ||, and ! within the callback function to apply conditional logic. For example:

const orders = [
{ id: 1, status: 'pending', totalAmount: 100 },
{ id: 2, status: 'shipped', totalAmount: 200 },
{ id: 3, status: 'pending', totalAmount: 50 },
];

const pendingOrdersWithTotalAmountOver100 = orders.filter(
(order) => order.status === 'pending' && order.totalAmount > 100
);

console.log(pendingOrdersWithTotalAmountOver100);
// []

This code filters the orders array to include only orders with a pending status and a total amount greater than 100. In this case, no orders match both criteria, resulting in an empty array.

You can also use the TypeScript ternary operator within filter callbacks to create conditional expressions that determine whether an element should be included.

When working with database filtering in Convex, you can use similar conditional logic patterns to query your data efficiently.

Using Custom Type Guards with Array Filter

To use custom type guards with filter, define a function that narrows the type of the elements in the array. For example:

function isString<T>(value: T): value is T & string {
return typeof value === 'string';
}

const values: (string | number)[] = ['a', 1, 'b', 2];

const strings = values.filter(isString);

console.log(strings); // ['a', 'b']

This code defines a custom type guard isString that narrows the type of the elements in the values array to string. TypeScript understands that the strings array will only contain string values, providing complete type safety.

TypeScript generics make this pattern powerful and reusable across different array types. By using function type annotations correctly, you ensure the compiler properly infers the resulting array type.

When working with Convex, the filter helper from convex-helpers provides similar type narrowing capabilities for database queries, allowing you to write type-safe filters with unlimited flexibility.

Ensuring Strict Type Checking with Array Filter

To maintain strict type checking, make sure the callback function returns a type assignable to the type parameter of the filter method. For instance:

const maybeStrings: (string | undefined)[] = ['a', undefined, 'b'];

const strings = maybeStrings.filter((value): value is string => value !== undefined);

console.log(strings); // ['a', 'b']

This code ensures that the strings array only contains string values by using a type predicate. The explicit return type annotation value is string tells TypeScript that the resulting array will contain only strings, not undefined values.

TypeScript type assertion could also work here, but using type predicates provides better type safety because TypeScript verifies the predicate logic.

With TypeScript 5.5, the compiler can now automatically infer type predicates in many common filtering scenarios, making your code more concise while maintaining type safety.

When using the Convex database, similar type checking mechanisms help ensure your database queries return properly typed results.

Removing Undefined or Null Values from an Array

You can remove undefined or null values from an array by using the filter method with a callback function that checks for these values. For example:

const values: (string | null | undefined)[] = ['a', null, 'b', undefined];

const nonNullValues = values.filter((value): value is string => value !== null && value !== undefined);

console.log(nonNullValues); // ['a', 'b']

This code removes null and undefined values from the values array, resulting in an array that only contains string values. The type predicate ensures TypeScript correctly infers the return type.

For simpler cases, you can use the TypeScript array method with a shorter Boolean callback: values.filter(Boolean). However, this approach might not provide the same level of type inference without additional type assertions.

When working with arrays that might contain nullable values in Convex database queries, you can use similar filtering techniques to ensure you only retrieve the data you need.

The TypeScript 5.5 release improves type inference when filtering arrays, making it easier to work with nullable types in filtered arrays.

Filtering Arrays with Multiple Criteria

To filter an array with multiple criteria, use the logical operators &&, ||, and ! within the callback function. For instance:

const users: { id: number; name: string; age: number; active: boolean }[] = [
{ id: 1, name: 'John', age: 25, active: true },
{ id: 2, name: 'Jane', age: 30, active: false },
{ id: 3, name: 'Bob', age: 20, active: true },
];

const activeUsersOver25 = users.filter((user) => user.active && user.age > 25);

console.log(activeUsersOver25);
// []

This code filters the users array to include only active users over 25 years old. Since no users match both criteria, the result is an empty array.

You can combine as many conditions as needed to build complex filtering logic. For more advanced scenarios, consider using the TypeScript reduce method after filtering to transform or aggregate the filtered data.

When working with complex data structures, you might need to use foreach or map alongside filter to process your data further.

For database queries in Convex, the complex filters helper allows you to write TypeScript filters with unlimited functionality while maintaining strong type safety.

Final Thoughts about TypeScript Array Filter

The TypeScript array filter method is an essential tool for creating new arrays with selected elements. It lets you extract exactly the data you need while maintaining type safety, even with complex data structures. Whether you're filtering simple arrays, working with objects, or handling nullable values, TypeScript's type system ensures your filtered results match your expectations.

By using type guards and predicates, you can create filters that both narrow types and select elements, making your code more robust. And when your filtering needs grow more complex, combining filter with other array methods gives you effective data transformation capabilities.

For Convex users, similar filtering techniques apply to database queries, letting you write type-safe, efficient filters with the filter helper and database filters.