To find an object in an array in TypeScript, use the array find() method with a condition on a property: products.find(p => p.id === 102) returns the first matching object, or undefined if there is none. TypeScript types the result as Product | undefined, so you must handle the missing case. This guide covers TypeScript array find by property value, findIndex() and findLast(), why includes() does not find an equal object, searching by several properties, a generic findBy helper, type guards, and fast lookups with a Map.
Every example was compiled with TypeScript 5.2.2 and Node.js v22.22.2 in the Windows Command Prompt, using tsc --target es2022 --lib es2023,dom --strict file.ts and node file.js. Reference: Array.prototype.find() on MDN and Narrowing in the TypeScript Handbook.
Find an object in an array by property
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const hub = products.find(p => p.id === 102); // Product | undefined
console.log(hub);
const lamp = products.find(p => p.name === "Desk Lamp");
console.log(lamp?.price);
const missing = products.find(p => p.id === 999);
console.log(missing); // undefined when nothing matches
Output:
{ id: 102, name: 'USB-C Hub', category: 'electronics', price: 25 }
45
undefined
find() returns the first matching object, or undefined.find() stops at the first match, so it is efficient for one lookup. The callback can use any condition; p.id === 102 is the most common one.
Handle the undefined result
With strict mode on, TypeScript does not let you use the result as if it was always found:
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const webcam = products.find(p => p.name === "Webcam");
console.log(webcam.price);
tsc output:
find_undefined_error.ts(16,13): error TS18048: 'webcam' is possibly 'undefined'.
find() can be undefined, and the compiler knows it.Check the result with if, use optional chaining with a default, or throw a clear error when the object must exist. Avoid the non-null assertion webcam!.price: it silences the compiler but still crashes at run time if nothing matches.
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const webcam = products.find(p => p.name === "Webcam");
if (webcam) {
console.log(`${webcam.name}: $${webcam.price}`); // narrowed to Product
}
console.log(webcam?.category ?? "not found"); // optional chaining + default
function getProduct(id: number): Product {
const found = products.find(p => p.id === id);
if (!found) throw new Error(`Product ${id} not found`);
return found;
}
console.log(getProduct(101).name);
try { getProduct(500); } catch (e) { console.log((e as Error).message); }
Output:
Webcam: $69
electronics
Laptop Stand
Product 500 not found
Find the index of an object: findIndex, findLast and findLastIndex
findIndex() returns the position of the first match (-1 if none), which is what you need to replace or remove the object. findLast() and findLastIndex() search from the end; they need "lib": ["es2023"] in tsconfig.json and Node.js 18 or later:
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
console.log(products.findIndex(p => p.id === 103)); // 2
console.log(products.findIndex(p => p.id === 999)); // -1
console.log(products.findLast(p => p.category === "office")?.name); // last match (ES2023)
console.log(products.findLastIndex(p => p.price < 50)); // 2
const i = products.findIndex(p => p.id === 102);
if (i !== -1) products[i] = { ...products[i], price: 22 }; // update the found object
console.log(products[i]);
Output:
2
-1
Desk Lamp
2
{ id: 102, name: 'USB-C Hub', category: 'electronics', price: 22 }
Why includes() does not find an equal object
includes() and indexOf() compare objects by reference, not by their values. To check whether an array contains an object with certain properties, use some(); to get every match, use filter():
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const copy = { id: 101, name: "Laptop Stand", category: "office", price: 39 };
console.log(products.includes(copy)); // false: different object, same values
console.log(products.includes(products[0])); // true: the same object reference
console.log(products.some(p => p.id === copy.id)); // true: compare by property
console.log(products.filter(p => p.category === "electronics").map(p => p.name)); // all matches
Output:
false
true
true
[ 'USB-C Hub', 'Webcam' ]
includes() checks identity; some() and filter() check properties.Search by several properties and a generic findBy helper
Combine conditions with &&, and lowercase both sides for a case-insensitive search. The generic helper only accepts real property names and a value of the matching type (T[K]):
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const term = "desk";
const byName = products.find(p => p.name.toLowerCase().includes(term.toLowerCase()));
console.log(byName?.name);
const cheapOffice = products.find(p => p.category === "office" && p.price < 40);
console.log(cheapOffice?.name);
function findBy<T, K extends keyof T>(items: readonly T[], key: K, value: T[K]): T | undefined {
return items.find(item => item[key] === value);
}
console.log(findBy(products, "category", "electronics")?.name);
console.log(findBy(products, "price", 69)?.name);
Output:
Desk Lamp
Laptop Stand
USB-C Hub
Webcam
Narrow the type of the found object
When the array holds a union type, a type predicate in the callback makes find() return the narrower type:
type Admin = { role: "admin"; name: string; permissions: string[] };
type Guest = { role: "guest"; name: string };
type User = Admin | Guest;
const users: User[] = [
{ role: "guest", name: "Ana" },
{ role: "admin", name: "Raj", permissions: ["publish", "delete"] },
];
const admin = users.find((u): u is Admin => u.role === "admin"); // Admin | undefined
console.log(admin?.permissions.join(", "));
Output:
publish, delete
Many lookups by id: use a Map
find() scans the array every time. If you look up many ids in a large array, build a Map once and use get():
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const products: Product[] = [
{ id: 101, name: "Laptop Stand", category: "office", price: 39 },
{ id: 102, name: "USB-C Hub", category: "electronics", price: 25 },
{ id: 103, name: "Desk Lamp", category: "office", price: 45 },
{ id: 104, name: "Webcam", category: "electronics", price: 69 },
];
const byId = new Map(products.map(p => [p.id, p])); // build once: Map<number, Product>
console.log(byId.get(104)?.name);
console.log(byId.has(999));
console.log(byId.size);
Output:
Webcam
false
4
| Goal | Method | Returns |
|---|---|---|
| First object that matches | arr.find(fn) | The object or undefined |
| Its position | arr.findIndex(fn) | Index or -1 |
| Last match | arr.findLast(fn) | The object or undefined |
| All matches | arr.filter(fn) | A new array (may be empty) |
| Does any match? | arr.some(fn) | true / false |
| Repeated lookups by key | new Map(arr.map(o => [o.id, o])) | map.get(id) |
Keep learning with these TypeScript array guides:
- Sort an array of objects by property in TypeScript
- Filter an array of objects in TypeScript
- Check if a TypeScript array contains a value
- Use an interface for an array of objects
Frequently asked questions
How do I find an object in an array by property in TypeScript?
Use find(): const item = arr.find(o => o.id === 42);. The result type is T | undefined.
What does find() return if nothing matches?
undefined. Check it with if (item) or use item?.name before reading properties.
How do I get the index of an object in an array?
arr.findIndex(o => o.id === 42) returns the index, or -1 if there is no match.
Why does includes() return false for an object that is in the array?
includes() compares objects by reference. A copy with the same values is a different object; use arr.some(o => o.id === x.id).
How do I find all objects that match?
Use filter(), which returns a new array with every match.
Why does TypeScript say the object is possibly undefined?
Because find() may not find anything. Narrow the value with an if check or optional chaining instead of using !.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn