Skip to content

noArrayForEach (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noArrayForEach": "error"
}
}
}
}

Disallow the forEach() method in favor of for...of loops.

A for...of loop runs the same code for each item of an array, and it has several advantages over passing a function to forEach():

  • break stops the loop early, and continue skips to the next item.
  • return and await apply to the surrounding function, so you can leave that function or wait for a promise from inside the loop.
  • In TypeScript, a type checked before the loop is still known inside the loop, because the loop body is not a separate function.

Use array.entries() when you also need the index of each item: for (const [index, item] of array.entries()).

This rule doesn’t report calls when the value is known not to be an array, such as a Map or a Set, either because it is created with new Map() or because its type annotation says so. It also ignores forEach() from the following libraries, because they take the list as an argument instead of looping over the value they’re called on: React.Children, Children, R (Ramda), pIteration, Effect, and namespace imports of strict-callbag-basics.

array.forEach((element) => {
bar(element);
});
code-block.js:1:7 lint/nursery/noArrayForEach ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This forEach() call can be written as a for...of loop.

> 1 │ array.forEach((element) => {
│ ^^^^^^^
2 │ bar(element);
3 │ });

ℹ A for...of loop can use break and continue, and return and await inside it apply to the surrounding function.

ℹ Replace this call with a for...of loop. Loop over entries() if you also need the index.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

array?.forEach((element) => {
bar(element);
});
code-block.js:1:8 lint/nursery/noArrayForEach ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This forEach() call can be written as a for...of loop.

> 1 │ array?.forEach((element) => {
│ ^^^^^^^
2 │ bar(element);
3 │ });

ℹ A for...of loop can use break and continue, and return and await inside it apply to the surrounding function.

ℹ Replace this call with a for...of loop. Loop over entries() if you also need the index.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

array.forEach((element, index) => {
bar(element, index);
});
code-block.js:1:7 lint/nursery/noArrayForEach ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This forEach() call can be written as a for...of loop.

> 1 │ array.forEach((element, index) => {
│ ^^^^^^^
2 │ bar(element, index);
3 │ });

ℹ A for...of loop can use break and continue, and return and await inside it apply to the surrounding function.

ℹ Replace this call with a for...of loop. Loop over entries() if you also need the index.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

for (const element of array) {
bar(element);
}
for (const [index, element] of array.entries()) {
bar(element, index);
}
const map = new Map();
map.forEach((value, key) => bar(key, value));
function log(set: Set<string>) {
set.forEach((value) => console.log(value));
}
  • noForEach also reports forEach() calls, but allows callbacks that use the index of each item.