返回

TypeScript 联合类型索引签名错误终极指南:彻底解决 \

javascript

解决 TypeScript 中索引签名联合类型错误的终极指南

前言

索引签名是一种强大的 TypeScript 特性,允许你使用字符串或数字作为对象的键。但是,当涉及到联合类型时,有时可能会遇到一个棘手的错误:"索引签名参数类型不能是联合类型"。

问题

当你尝试使用联合类型作为索引签名的参数类型时,TypeScript 会报错。这是因为索引签名通常期望一个单一的类型,而不是一个联合类型。例如:

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

interface OptionRequirements {
  [key in Option | string]: OptionRequirement;
}

编译此代码时,你会看到以下错误:

Type 'Option | string' is not assignable to type 'Option'.
  'string' is not assignable to type 'Option'.

解决方案:使用映射对象类型

解决此错误的一种方法是使用映射对象类型。映射对象类型允许你为对象的不同键指定不同的类型。在这种情况下,你可以使用以下映射对象类型来定义 OptionRequirements 接口:

interface OptionRequirements {
  [key in Option]: OptionRequirement;
}

在这里,OptionRequirements 接口被定义为一个映射对象类型,其中键的类型是 Option 枚举,而值的类型是 OptionRequirement 接口。这允许你为 OptionRequirements 对象的每个键指定一个不同的 OptionRequirement 对象。

示例代码

以下是如何使用映射对象类型来修复你的示例代码:

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

interface OptionRequirements {
  [key in Option]: OptionRequirement;
}

const optionRequirements: OptionRequirements = {
  ONE: { someBool: true, someString: 'one' },
  TWO: { someBool: false, someString: 'two' },
  THREE: { someBool: true, someString: 'three' },
};

使用映射对象类型后,你应该不再收到 "索引签名参数类型不能是联合类型" 错误。

其他技巧

  • 使用联合枚举类型: 如果你需要索引签名的参数类型是一个联合类型,但仍然希望保持类型的安全性,可以使用联合枚举类型。例如:
enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

type OptionOrString = Option | string;

interface OptionRequirements {
  [key in OptionOrString]: OptionRequirement;
}
  • 使用类型保护: 在某些情况下,你可以使用类型保护来检查联合类型中的实际类型。例如:
interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

interface OptionRequirements {
  [key: string]: OptionRequirement | undefined;
}

const optionRequirements: OptionRequirements = {
  ONE: { someBool: true, someString: 'one' },
  TWO: { someBool: false, someString: 'two' },
  THREE: undefined,
};

if (optionRequirements['ONE'] && 'someBool' in optionRequirements['ONE']) {
  // 在这里,你可以安全地访问 'someBool' 属性。
}

结论

使用索引签名时遇到 "索引签名参数类型不能是联合类型" 错误并不罕见。然而,通过使用映射对象类型和其他技巧,你可以轻松解决此错误并充分利用 TypeScript 中索引签名的强大功能。

常见问题解答

  1. 什么是索引签名?
    索引签名是一种 TypeScript 特性,允许你使用字符串或数字作为对象的键。

  2. 为什么会出现 "索引签名参数类型不能是联合类型" 错误?
    此错误发生在尝试使用联合类型作为索引签名的参数类型时。

  3. 如何使用映射对象类型来解决此错误?
    通过定义一个映射对象类型,其中键的类型是联合类型,而值的类型是另一个类型。

  4. 除了映射对象类型,还有哪些其他解决此错误的方法?
    你可以使用联合枚举类型或类型保护。

  5. 何时应该使用联合枚举类型或类型保护?
    如果你需要保持类型的安全性,请使用联合枚举类型。如果你需要检查联合类型中的实际类型,请使用类型保护。