Skip to content
← Back to rules

unicorn/no-useless-iterator-to-array Nursery

🛠️ 💡 An auto-fix and a suggestion are available for this rule.

它的作用

禁止在迭代器上不必要地使用 .toArray()

为什么这很糟糕?

Iterator.prototype.toArray() 会将迭代器转换为数组。然而,在许多情况下,这种转换是不必要的:

  • 以下内建对象可直接接受可迭代对象:
    • Map 构造函数
    • WeakMap 构造函数
    • Set 构造函数
    • WeakSet 构造函数
    • TypedArray 构造函数
    • Array.from(…)
    • TypedArray.from(…)
    • Object.fromEntries(…)
  • for…of 可以遍历任何可迭代对象,因此先转换为数组是不必要的。
  • yield* 可以委托给任何可迭代对象,因此先转换为数组是不必要的。
  • Promise.{all,allSettled,any,race}(…) 接受可迭代对象,因此 .toArray() 是不必要的。 这里移除 .toArray() 可能会在迭代失败时将同步抛出改为异步拒绝, 因此这些情况被视为建议,而不是自动修复。
  • 展开运算符(...)可用于任何可迭代对象,因此先转换为数组是不必要的。
  • 某些 Array 方法在 Iterator 上也存在,因此先转换为数组再调用它们是不必要的:
    • .every()
    • .find()
    • .forEach()
    • .reduce()
    • .some()

Array 回调会接收额外参数(例如第 3 个 array 参数),而 Iterator 回调不会。 如果回调依赖这些额外参数,移除 .toArray() 可能会改变行为,因此这些情况会被报告为建议。

此规则不会标记 .filter().map().flatMap(),因为它们在 Iterator 上的版本返回的是迭代器,而不是数组,因此语义不同。

示例

以下是此规则的错误代码示例:

js
const set = new Set(iterator.toArray());

const results = await Promise.all(iterator.toArray());

for (const item of iterator.toArray());

function* foo() {
  yield* iterator.toArray();
}

const items = [...iterator.toArray()];

call(...iterator.toArray());

iterator.toArray().every(fn);

以下是此规则的正确代码示例:

js
const set = new Set(iterator);

const results = await Promise.all(iterator);

for (const item of iterator);

function * foo() {
	yield * iterator;
}

const items = [...iterator];

call(...iterator);

iterator.every(fn);

`.filter()` 在 Array 上返回数组,但在 Iterator 上返回迭代器
iterator.toArray().filter(fn);

如何使用

To enable this rule using the config file or in the CLI, you can use:

json
{
  "rules": {
    "unicorn/no-useless-iterator-to-array": "error"
  }
}
ts
import { defineConfig } from "oxlint";

export default defineConfig({
  rules: {
    "unicorn/no-useless-iterator-to-array": "error",
  },
});
bash
oxlint --deny unicorn/no-useless-iterator-to-array

版本

此规则是在 v1.59.0 中添加的。

参考资料