noUnreadableForOfExpression (JavaScript)
Summary
Section titled “Summary”- Rule available since:
v2.6.3 - Diagnostic Category:
lint/nursery/noUnreadableForOfExpression - This rule doesn’t have a fix.
- The default severity of this rule is information.
- Sources:
How to configure
Section titled “How to configure”{ "linter": { "rules": { "nursery": { "noUnreadableForOfExpression": "error" } } }}Description
Section titled “Description”Disallow complex expressions as the value that a for...of loop goes through.
The parentheses of a for...of or for await...of loop hold two things: the variable
that receives each item, and the value that the loop goes through.
When that value is a long or nested expression, it is harder to see what the loop works on.
Storing the value in a variable before the loop gives it a name and keeps the loop easy to scan.
The rule accepts these expressions as the value to loop over:
- A variable,
this, an array such as[first, second], or a literal such as a string in quotes. A template string (a string in backticks) is not accepted here. - A property read with a dot, such as
object.items, when the part before the dot is also in this list. - A call such as
getItems(argument)orobject.getItems(argument). The function must be a variable or a property that is in this list, and every argument must be short. A short argument is a variable, a literal, a template string, a property read with a dot, a call without arguments, or an array of those.
The rule reports every other expression. Examples are a call that takes another call with
arguments, a new expression, an await expression, a condition such as first || second,
optional chaining (items?.values()), and a property read with brackets (items[index]).
A method call on such an expression is also reported, as in (first || second).values().
Two kinds of method calls follow their own rules:
- A call to
.map()or.filter()that produces the value to loop over is not reported, whatever its arguments are. - A call to
.map(),.filter(),.flatMap(),.take(), or.drop()on an iterator is always reported. An iterator is an object that produces its values one at a time. The rule recognizes the iterators returned by.entries(),.keys(),.values(),.matchAll(), methods called onIteratoritself such asIterator.from(), and generator functions (function*) declared in the same file. It also follows aconstvariable declared before the loop to the value that the variable holds.
Examples
Section titled “Examples”Invalid
Section titled “Invalid”for (const item of getItems(createArgument(seed))) { console.log(item);}code-block.js:1:20 lint/nursery/noUnreadableForOfExpression ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This for...of loop goes through the result of a complex expression.
> 1 │ for (const item of getItems(createArgument(seed))) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │ console.log(item);
3 │ }
ℹ A complex expression between the parentheses of a loop makes it harder to see what the loop works on.
ℹ Store the expression in a variable before the loop, and loop over that variable 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 key of Object.keys(Object.fromEntries(entries))) { console.log(key);}code-block.js:1:19 lint/nursery/noUnreadableForOfExpression ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This for...of loop goes through the result of a complex expression.
> 1 │ for (const key of Object.keys(Object.fromEntries(entries))) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │ console.log(key);
3 │ }
ℹ A complex expression between the parentheses of a loop makes it harder to see what the loop works on.
ℹ Store the expression in a variable before the loop, and loop over that variable 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 item of new Set(items)) { console.log(item);}code-block.js:1:20 lint/nursery/noUnreadableForOfExpression ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This for...of loop goes through the result of a complex expression.
> 1 │ for (const item of new Set(items)) {
│ ^^^^^^^^^^^^^^
2 │ console.log(item);
3 │ }
ℹ A complex expression between the parentheses of a loop makes it harder to see what the loop works on.
ℹ Store the expression in a variable before the loop, and loop over that variable 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 value of items.values().map(callback)) { console.log(value);}code-block.js:1:21 lint/nursery/noUnreadableForOfExpression ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This for...of loop goes through the result of a complex expression.
> 1 │ for (const value of items.values().map(callback)) {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │ console.log(value);
3 │ }
ℹ A complex expression between the parentheses of a loop makes it harder to see what the loop works on.
ℹ Store the expression in a variable before the loop, and loop over that variable 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 argument = createArgument(seed);for (const item of getItems(argument)) { console.log(item);}
for (const item of object.items) { console.log(item);}
for (const value of Object.values(object)) { console.log(value);}
for (const [index, item] of [first, second].entries()) { console.log(index, item);}
for (const item of items.filter(item => item.isEnabled)) { console.log(item);}Related links
Section titled “Related links”Copyright (c) 2023-present Biome Developers and Contributors.