How to Find an Object in an Array in TypeScript

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
Command Prompt showing a TypeScript file compiled with tsc and run with node that finds product objects in an array by id and name with find
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'.
Command Prompt showing tsc error TS18048 webcam is possibly undefined after Array.find in TypeScript
The result of 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 }
Command Prompt output of TypeScript findIndex, findLast and findLastIndex on an array of products and updating the found object by index
Find a position, then update the object at that index.

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' ]
Command Prompt output showing TypeScript includes returning false for an equal copy of an object, true for the same reference, and some and filter matching by property
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
GoalMethodReturns
First object that matchesarr.find(fn)The object or undefined
Its positionarr.findIndex(fn)Index or -1
Last matcharr.findLast(fn)The object or undefined
All matchesarr.filter(fn)A new array (may be empty)
Does any match?arr.some(fn)true / false
Repeated lookups by keynew Map(arr.map(o => [o.id, o]))map.get(id)

Keep learning with these TypeScript array guides:

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 !.