TypeScript

How to Get an Array Element and Its Index in TypeScript

Get an array item and its zero-based index in TypeScript with forEach, entries(), or an indexed loop—and know when to use map instead.

Editorial illustration for Iterate Over a TypeScript Array with Both Its Element and Index

If you need an array element and its position, start with forEach((element, index) => ...). The element comes first and the zero-based index comes second. Here is a Product[] that uses both callback parameters:

type Product = {
  name: string;
  price: number;
};

const products: Product[] = [
  { name: "Notebook", price: 8 },
  { name: "Pen", price: 2 },
  { name: "Folder", price: 5 },
];

products.forEach((product, index) => {
  console.log(`${index}: ${product.name}`);
});

For this array, the displayed pairs begin with 0: Notebook, then 1: Pen. product is the item at that position, not the index. The callback order matters: changing the parameter names would not change which value is passed first. An array iteration example from CodeVsColor uses the same element-then-index order to print each item beside its position.

Choose the callback for what it produces

Use forEach when the job is an action for each item, such as displaying the pairs above. If the callback should produce a new array, use map instead:

const labels = products.map((product) => product.name);

Here, labels is the new array of names. Calling map and ignoring that array obscures the intention; forEach is the clearer choice when there is nothing to collect. The array-method comparison draws this practical distinction between an action on each element and creating a new array.

Destructure index and element with entries()

When a pair reads more clearly than callback parameters, iterate over the array’s entries:

for (const [index, product] of products.entries()) {
  console.log(`${index}: ${product.name}`);
}

Notice the order in [index, product]: the index comes first, unlike the element-first forEach callback. That small difference is worth checking when switching between the two forms. A comparison of indexed loops and entries() shows both ways to process an item with its position. If the entries() form is unavailable in your project, use the indexed loop below.

Keep the counter when it controls traversal

An indexed for loop is less compact, but its counter can decide whether to visit an item. This example stops before position 2:

for (let index = 0; index < products.length; index++) {
  if (index === 2) break;

  const product = products[index];
  if (product === undefined) continue;

  console.log(`${index}: ${product.name}`);
}

The bracket expression reads the item at the counter’s position. The undefined check means this example does not use product.name when that read yields no item. The indexed-loop example likewise starts at zero and checks the counter against the array length. Unlike a forEach callback, the loop also has direct break and continue control.

Check these examples in your project rather than assuming every editor and runtime is configured alike. Type-check them to see how your configuration treats the callback parameters, the destructured pair, and the indexed read. Then run the short array: the first displayed pair should be 0: Notebook, and the stopping loop should display only positions 0 and 1. That run checks the stopping behavior; a type check by itself does not tell you whether you chose the intended stopping position.

Find a note

Search by topic, title, or keyword.