Skip to content

Latest commit

Β 

History

History
73 lines (50 loc) Β· 2.82 KB

prefer-iterator-to-array-at-end.md

File metadata and controls

73 lines (50 loc) Β· 2.82 KB

prefer-iterator-to-array-at-end

πŸ“ Prefer moving .toArray() to the end of iterator helper chains.

πŸ’Ό This rule is enabled in the following configs: βœ… recommended, β˜‘οΈ unopinionated.

πŸ’‘ This rule is manually fixable by editor suggestions.

Prefer moving Iterator#toArray() to the end of iterator helper chains.

Iterator helpers are lazy. Calling toArray() before helper methods like map() or filter() creates a temporary array and makes the rest of the chain use Array methods instead of lazy Iterator methods.

Examples

// ❌
const result = iterator.toArray().map(element => element * 2);

// βœ…
const result = iterator.map(element => element * 2).toArray();
// ❌
const result = iterator.toArray().filter(element => element > 1);

// βœ…
const result = iterator.filter(element => element > 1).toArray();

A named callback is not reported. Array callbacks receive the element, the index and the array, while Iterator callbacks receive only the element, so a callback that reads the third argument would stop working. A callback declared with one or two parameters is safe and is reported:

// βœ… Not reported, its parameter list is not visible here
const result = iterator.toArray().map(callback);

Cases are reported as suggestions instead of autofixes because moving toArray() changes when callbacks run: Array methods run after the iterator has been exhausted, while Iterator helpers run lazily as the result is consumed. Array callbacks also receive an extra array argument that Iterator callbacks do not.

flatMap() has an additional difference: Array#flatMap() accepts non-iterable callback results, while Iterator#flatMap() requires iterable results.

// ❌
const result = iterator.toArray().flatMap(element => [element, element]);

// βœ…
const result = iterator.flatMap(element => [element, element]).toArray();

toArray() is also a common user-defined method name, so a receiver that is known not to be an Iterator is left alone. That covers a const bound to an object, an array, a literal, or an instance of a class declared in the same file:

// βœ…
class Vector {
	toArray() {
		return [1, 2, 3];
	}
}

const vector = new Vector();
const result = vector.toArray().map(element => element * 2);

A bare call is not resolved, because map.values() is a call too, so a user-defined toArray() on a call result is still reported:

// ❌
const result = makeVector().toArray().map(element => element * 2);

This rule only handles direct lazy helper equivalents. It intentionally does not convert Array#slice() to Iterator#take() or Iterator#drop().