Skip to content

useIteratorZip (JavaScript)

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

Prefer Iterator.zip() over reading several arrays with the same index.

A for loop that stops at the end of the shortest array, and uses its index only to read the same position from each array, can be written as a for...of loop over Iterator.zip(). Iterator.zip() returns the elements at the same position together and stops at the end of the shortest array, so the loop needs neither an index nor a length check.

The rule reports a for loop when all of the following are true:

  • The index is declared with let, starts at 0, and increases by one after each iteration.
  • The loop stops at the end of the shortest of two or more arrays. Each array must be a variable, not a property such as object.names. The condition either compares the index to Math.min() of the array lengths, or compares the index to each length and joins the comparisons with &&. The result of Math.min() can also be stored in a variable, as long as the variable is declared in the loop or in the statement right before it, and only the loop condition uses it.
  • The body is a block that uses the index and the arrays only to read array[index], and it reads every array at least once.

The rule ignores a loop when its body changes, calls, or deletes an array element, or when it uses the index or an array inside a nested function or class.

Iterator.zip() only accepts values that can be looped over with for...of, and it doesn’t accept strings. The rule therefore ignores a loop when it can tell that one of the variables holds something other than an array, such as a string, an object literal, a Map, or a Set.

for (let index = 0; index < Math.min(names.length, scores.length); index++) {
save(names[index], scores[index]);
}
code-block.js:1:1 lint/nursery/useIteratorZip ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ This for loop only uses its index to read the same position from several arrays.

> 1 │ for (let index = 0; index < Math.min(names.length, scores.length); index++) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │ save(names[index], scores[index]);
3 │ }

ℹ Iterator.zip() returns the elements at the same position together and stops at the end of the shortest array, so the loop needs neither an index nor a length check.

ℹ Use a for...of loop over Iterator.zip() instead.

ℹ 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 (let index = 0; index < names.length && index < scores.length; index++) {
save(names[index], scores[index]);
}
code-block.js:1:1 lint/nursery/useIteratorZip ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ This for loop only uses its index to read the same position from several arrays.

> 1 │ for (let index = 0; index < names.length && index < scores.length; index++) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │ save(names[index], scores[index]);
3 │ }

ℹ Iterator.zip() returns the elements at the same position together and stops at the end of the shortest array, so the loop needs neither an index nor a length check.

ℹ Use a for...of loop over Iterator.zip() instead.

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

const length = Math.min(names.length, scores.length);
for (let index = 0; index < length; index++) {
save(names[index], scores[index]);
}
code-block.js:2:1 lint/nursery/useIteratorZip ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ This for loop only uses its index to read the same position from several arrays.

1 │ const length = Math.min(names.length, scores.length);
> 2 │ for (let index = 0; index < length; index++) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 │ save(names[index], scores[index]);
4 │ }

ℹ Iterator.zip() returns the elements at the same position together and stops at the end of the shortest array, so the loop needs neither an index nor a length check.

ℹ Use a for...of loop over Iterator.zip() instead.

ℹ 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 [name, score] of Iterator.zip([names, scores])) {
save(name, score);
}
// The index is used for something other than reading the arrays.
for (let index = 0; index < Math.min(names.length, scores.length); index++) {
save(index, names[index], scores[index]);
}
// The loop changes one of the arrays.
for (let index = 0; index < Math.min(names.length, scores.length); index++) {
names[index] = scores[index];
}
// The loop reads a single array.
for (let index = 0; index < names.length; index++) {
save(names[index]);
}
// `Iterator.zip()` doesn't accept strings.
const letters = "abc";
for (let index = 0; index < Math.min(letters.length, scores.length); index++) {
save(letters[index], scores[index]);
}