11

我有一个枚举。我想使用它的值来为这些值成为键的对象创建类型。以下示例演示了我想要实现的目标:

export enum MyEnum {
  PROP_1 = "prop 1",
  PROP_2 = "prop 2",
  // ... more props
}

export interface MyInterface {
  property: {
    "prop 1": boolean,
    "prop 2": boolean,
    // ... more props
  }
}

它工作正常,但我想避免在界面中重复枚举中的所有属性。

是否可以执行以下操作:

export enum MyEnum {
  PROP_1 = "prop 1",
  PROP_2 = "prop 2",
  // ... more props
}

// PSEUDOCODE!
export interface MyInterface {
  property: {
    [values from MyEnum]: boolean
  }
}

更新:

感谢@jcalz 的解决方案:

enum MyEnum {
  PROP_1 = "prop 1",
  PROP_2 = "prop 2",
  // ... more props
}

interface PropertyInterface extends Record<MyEnum, boolean> {}

interface MyInterface {
  property: PropertyInterface,
}

根据我之前写的内容,它工作得很好,但我刚刚意识到我忘了提到我需要所有这些属性都是可选的。

如果实现的变量MyInterface定义如下,则给定的解决方案有效:

// VALID!
const myVariable: MyInterface = {
  property: {
    "prop 1": true,
    "prop 2": true,
  },
};

但是,如果我省略了如下一些键,则不起作用:

// INVALID :(
const myVariable: MyInterface = {
  property: {
    "prop 1": true,
  },
};
4

1 回答 1

35

TypeScript 2.9 中添加了对此的支持,作为扩展键支持映射类型的一部分。具体来说:

映射类型{ [P in K]: XXX }允许任何K可分配给string | number | symbol

这意味着您可以使用枚举值作为键为映射类型创建类型别名:

enum MyEnum {
  PROP_1 = "prop 1",
  PROP_2 = "prop 2",
  // ... more props
}

type MyEnumValuedKeys = { [K in MyEnum]: boolean; }
// identical to 
// type MyEnumValuedKeys = {
//  "prop 1": boolean;
//  "prop 2": boolean;
//  ... more props
// }

?您可以通过在类似索引的键后添加 a 来使映射类型属性成为可选:

type OptionalMyEnumValuedKeys = { [K in MyEnum]?: boolean; }
// identical to 
// type MyEnumValuedKeys = {
//  "prop 1"?: boolean;
//  "prop 2"?: boolean;
//  ... more props
// }

所以你可以OptionalMyEnumValuedKeys用作你的PropertyInterface. 它是类型别名而不是接口。这通常无关紧要,但万一发生了,TypeScript 2.8 引入了扩展某些具体映射类型的能力,因此您可以获得这样的接口:

type OptionalMyEnumValuedKeys = { [K in MyEnum]?: boolean; };
interface PropertyInterface extends OptionalMyEnumValuedKeys {} // add no properties

这也可以通过使用内置RecordPartial类型别名来完成:

interface PropertyInterface extends Partial<Record<MyEnum, boolean>> {}

好的,希望有帮助。祝你好运!

于 2018-10-31T13:17:02.403 回答