Iterator objects should not be misused as arrays
- MISUSED_ITERATOR
- Error
- High, Medium
- No tags
This rule applies when an iterator object is misused as an array.
An iterator object provides the next
method that returns each element on successive calls. Built-in iterator objects are created in the following places:
- The return value of generator or async generator function
- The return value of
String.prototype.matchAll()
This rule detects the following misuses of built-in iterator objects:
- Iterating with
for-in
loop: In this case, the loop ends immediately because the built-in iterator objects have no enumerable properties. You should usefor-of
orfor-await-of
(for async generator) loop instead. - Calling array methods: In this case, a
TypeError
exception is thrown. You should convert the iterator to an array usingArray.from()
or array spread operator. - Accessing the
length
property: In this case, anundefined
value is read because iterators do not have thelength
property.
Noncompliant Code Example
View with compliant examples side by side// Example 1
function *countDown() {
yield 3;
yield 2;
yield 1;
yield 0;
}
for (let n in countDown()) { // MISUSED_ITERATOR alarm
console.log(n);
}
// Example 2
const scores = "ID[1]: 90, 80, 100".matchAll(/\d+/g);
scores.shift(); // MISUSED_ITERATOR alarm
// Example 3
const uppers = "Foo Bar Baz".matchAll(/[A-Z]/g);
for (let i = 0; i < uppers.length; i++) { // MISUSED_ITERATOR alarm
doSomething(i, uppers.next().value);
}
Compliant Code Example
View with noncompliant examples side by side// Example 1
function *countDown() {
yield 3;
yield 2;
yield 1;
yield 0;
}
for (let n of countDown()) {
console.log(n);
}
// Example 2
const numberMatches = "ID[1]: 90, 80, 100".matchAll(/\d+/g);
const scores = [...numberMatches];
scores.shift();
// Example 3
const uppers = "Foo Bar Baz".matchAll(/[A-Z]/g);
let i = 0;
for (let letter of uppers) {
doSomething(i++, letter);
}
Version
This rule was introduced in DeepScan 1.45.0.