Use array.filter(item => condition) to keep objects that match a property. If the array contains a union of object types and you want the result narrowed to one type, pass a type predicate instead. For checks that remove null or undefined, TypeScript 5.5 can infer the narrower result type from qualifying comparisons.
Filter objects by a property
filter returns a new array containing the elements for which its callback returns true. For an ordinary array whose elements all have the same object type, write the condition that describes which objects should remain:
type User = { id: number; name: string; active: boolean };
const users: User[] = [
{ id: 1, name: "Ada", active: true },
{ id: 2, name: "Lin", active: false },
];
const activeUsers = users.filter(user => user.active);
// User[]
The callback can use any boolean condition. For example, use user.role === "admin" to match a role, user.age >= 18 to check a threshold, or user.name.startsWith("A") to match a name prefix. The result remains User[]: filtering selects elements but does not change their element type. TypeScript supports both User[] and the equivalent generic form Array<User> for array types; see the Handbook’s object types documentation.
Narrow a union array to one object type
If an array contains different object types, an ordinary boolean callback may select the right values at runtime without telling TypeScript that the result is just one member of the union. Give the callback a type-predicate return type:
#1 Best Overall
type Fish = { swim: () => void; name: string };
type Bird = { fly: () => void; name: string };
type Pet = Fish | Bird;
function isFish(pet: Pet): pet is Fish {
return "swim" in pet;
}
const pets: Pet[] = [];
const fish = pets.filter(isFish); // Fish[]
The form parameterName is Type tells TypeScript to treat values accepted by the predicate as that type. The check must justify the claim: TypeScript trusts an explicit predicate and does not prove that its implementation is logically sound. The Handbook’s narrowing guide covers predicates and in-based narrowing.
Use a discriminant when the union has a tag
For a discriminated union, comparing its literal tag is often a clear way to select a member:
Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
type Result =
| { kind: "success"; value: string }
| { kind: "error"; message: string };
const results: Result[] = [];
const errors = results.filter(
(result): result is Extract<Result, { kind: "error" }> =>
result.kind === "error"
);
Here, the equality check matches the "error" member, and the predicate communicates the narrower result type. An in check instead asks whether an object has a property. When that property is optional, it can be possible on both sides of a union, so its presence may not uniquely identify a member. See the Handbook’s section on the in operator.
Filter out null or undefined
When the unwanted value is specifically undefined or null, compare against it directly:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →const values: Array<number | undefined> = [1, undefined, 3];
const definedValues = values.filter(value => value !== undefined);
// number[] with TypeScript 5.5 predicate inference
type User = { id: number; name: string; active: boolean };
const maybeUsers: Array<User | null> = [];
const presentUsers = maybeUsers.filter(user => user !== null);
// User[] with TypeScript 5.5 predicate inference
TypeScript 5.5 documents inference of type predicates for qualifying callback checks like these. On an older compiler, the result may retain the wider element type; if you need a reusable guard, state the predicate explicitly:
function isDefined<T>(value: T | undefined): value is T {
return value !== undefined;
}
const defined = values.filter(isDefined);
Use a precise comparison rather than filter(Boolean) when falsy values can be legitimate data. A truthiness check also discards 0, false, and "", not just absent values. For example, choose value !== undefined when only undefined should be removed. The TypeScript 5.5 notes discuss both predicate inference and why truthiness checks on primitive values can be ambiguous: TypeScript 5.5 release notes.
What changes with TypeScript versions?
- TypeScript 5.5: qualifying callback checks, including comparisons with
nullorundefined, can be inferred as type predicates. Older compiler versions may need an explicit guard for a narrowed result. The behavior is documented in the 5.5 release notes. - TypeScript 5.2: method calls such as
filterwork more readily on unions of arrays. For an input typedstring[] | number[], the result may be typed as an array of the element union,(string | number)[], rather than a union of the original array types. See TypeScript 5.2 release notes.
When to use a reusable helper
For a one-off condition, calling filter directly is usually clearest. If the same filtering abstraction is repeated, a simple generic helper can accept an array and a boolean-returning callback:
function filterItems<T>(
items: T[],
predicate: (item: T) => boolean
): T[] {
return items.filter(predicate);
}
This helper preserves the input element type; its callback returns only boolean, so it does not express a narrower result type. If the helper must narrow a union, its callback signature must preserve a type predicate. The Handbook’s functions guide explains generic function patterns and recommends avoiding unnecessary type parameters.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




