Skip to content

Set 去重出现 'downlevelIteration' 错误的解决方案

问题描述

在使用 TypeScript 和 React 开发时,当你尝试使用 [...new Set(array)] 语法来去除数组中的重复元素时,可能会遇到以下 TypeScript 错误:

Type 'Set<unknown>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher

这个错误表示 TypeScript 编译器无法在当前配置下正确编译扩展运算符 ... 与 Set 对象结合使用的语法。

原始问题代码示例

typescript
const uniqueMuscle = workoutexercices.map((exercice: any) => {
  let exercicesId = exercice.id;
  exercicesId = [...new Set(exercicesId)];
  return exercicesId;
});

根本原因

这个问题的根本原因是 TypeScript 的编译目标(target)设置过低。扩展运算符 ... 与 Set 对象的结合使用需要 ES2015(ES6) 或更高版本的 JavaScript 支持。

如果 tsconfig.json 中的 target 设置为 es5 或更低版本,TypeScript 无法将这种语法转换为兼容的 ES5 代码。

解决方案

方案一:修改 tsconfig.json 配置(推荐)

修改 TypeScript 配置文件,将编译目标设置为 ES2015 或更高版本:

json
{
  "compilerOptions": {
    "target": "es2015",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    // 其他配置保持不变...
  }
}

TIP

es2015es6 是等价的,两者都可以使用。现代项目建议使用 es2020esnext 以获得最新的 JavaScript 特性支持。

方案二:使用 Array.from() 方法替代

如果不希望修改 TypeScript 配置,可以使用 Array.from() 方法来替代扩展运算符:

typescript
exercicesId = Array.from(new Set(exercicesId));

这种方法与扩展运算符效果相同,但兼容性更好,可以在较低的 ES 版本中使用。

方案三:使用 filter 方法手动去重

作为另一种替代方案,可以使用数组的 filter 方法手动实现去重功能:

typescript
exercicesId = exercicesId.filter((value, index, array) => 
  array.indexOf(value) === index
);

这种方法虽然代码量稍多,但完全不依赖 Set 对象和扩展运算符,兼容性最好。

配置示例

以下是一个完整的、推荐的 tsconfig.json 配置示例:

json
{
  "compilerOptions": {
    "target": "es2020",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "jsxImportSource": "react"
  },
  "include": [
    "src"
  ]
}
json
{
  "compilerOptions": {
    "target": "es5", // 可能需要修改为 es2015 或更高
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

注意事项

WARNING

修改 target 为更高版本可能会影响代码的浏览器兼容性。请根据你的项目需求选择合适的 ES 版本。

INFO

如果使用的是 Create React App,默认的 targetes5。修改为更高版本后,可能还需要将 React.Node 改为 React.ReactNode

typescript
// 修改前
function Component(): React.Node {}

// 修改后
function Component(): React.ReactNode {}

总结

遇到 downlevelIteration 错误时,有三种主要解决方案:

  1. 修改 tsconfig.json:将 target 设置为 es2015 或更高版本(推荐)
  2. 使用 Array.from():替代扩展运算符语法
  3. 使用 filter 方法:手动实现去重功能

根据项目需求和兼容性要求选择最适合的方案。对于新项目,建议直接使用 ES2015 或更高版本作为编译目标。