在打字稿中使用枚举作为接口键

Posted

技术标签:

【中文标题】在打字稿中使用枚举作为接口键【英文标题】:Using enum as interface key in typescript 【发布时间】:2017-02-03 17:16:20 【问题描述】:

我想知道我是否可以在接口中使用枚举作为对象键.. 我已经为它构建了一个小测试:

export enum colorsEnum
red,blue,green


export interface colorsInterface
[colorsEnum.red]:boolean,
[colorsEnum.blue]:boolean,
[colorsEnum.green]:boolean

当我运行它时,我收到以下错误:

A computed property name in an interface must directly refer to a built-in symbol.

我做错了还是不可能?

【问题讨论】:

【参考方案1】:

要定义接口,必须提供成员名称而不是计算。

export interface colorsInterface 
    red: boolean;
    blue: boolean;
    green: boolean;

如果您担心保持枚举和界面同步,您可以使用以下方法:

export interface colorsInterface 
    [color: number]: boolean;


var example: colorsInterface = ;
example[colorsEnum.red] = true;
example[colorsEnum.blue] = false;
example[colorsEnum.green] = true;

TypeScript 非常高兴您将枚举作为索引传递,如果您决定重命名 red,那么重命名重构会将所有内容保持在一起。

【讨论】:

这没问题,但是如果我们想将键值(在签名中)限制为枚举的可用键而不是颜色:数字怎么办。 [color: key in colorsEnum] 正是这样做的,但要求您在创建此接口的新对象时提供所有枚举键......所以在我的情况下,我需要更强大的类型检查,但对于部分枚举键。现在,为了支持我的用例,我只是回退到在我的签名中使用原语:(【参考方案2】:

你可以试试 type:

export enum colorsEnum
    red, blue, green


export type colorsInterface = 
    [key in colorsEnum]: boolean;
;

let example: colorsInterface = 
    [colorsEnum.red]: true,
    [colorsEnum.blue]: false,
    [colorsEnum.green]: true
;

或者如果您不想使用所有键:添加一个?

export type colorsInterface = 
    [key in colorsEnum]?: boolean;
;

let example: colorsInterface = 
    [colorsEnum.red]: true,
    [colorsEnum.blue]: false
;

【讨论】:

哇,这甚至适用于字符串枚举export enum ColorsEnum red = "red", blue = "blue", green = "green", 这基本上就是 typescript Record 实用程序类型为您所做的。 typescriptlang.org/docs/handbook/…***.com/questions/51936369/… 这应该被标记为正确答案。 这正是我正在寻找的解决方案。谢谢!【参考方案3】:

好的,关键思想是将 Enum 转换为正确的类型并用它扩展接口: You can check it out in live code here.

const enum Enum 
    key1 = "value1",
    key2 = "value2",
    key3 = "value3",

type EnumKeys = keyof typeof Enum;
type EnumKeyFields = [key in EnumKeys]:boolean

interface IEnumExtended extends EnumKeyFields 
    KeyEx1:boolean;
    KeyEx2:string;


// Test it
const enumInstance: IEnumExtended = 

;

当您进入 enumInstance 时,您将获得 Enum 键而不是值的自动完成。

【讨论】:

太棒了,我也在寻找同样的东西。这应该是公认的答案。 你从这行“type EnumKeys = keyof typeof Enum;”获得了什么? 嗨@yehonatanyehezkel,我获得了订单,并且我注意到创建“类型”时 TS 编译器工作得更好。在执行[key in keyof typeof Enum]:boolean 时,编译器会抱怨,并且当代码未拆分为 2 行时,它就不那么容易理解了。另外,我想使用键而不是值。这些值可以是键的解释。 是否可以将其扩展为有一个用于布尔值的枚举和另一个用于字符串的枚举,并将它们组合成一个字段列表类型?或者也许将类型指定为值? 您可以为每个枚举键设置类型。是的,你可以extends多个 EnumKeyFields 类型作为你想要的接口,每个类型都有其他类型,只要确保键不同。【参考方案4】:

为什么不让它尽可能简单:

export enum Color 
    Red = 'red',
    Blue = 'blue',
    Green = 'green'


export interface IColors
    [Color.Red]: boolean,
    [Color.Blue]: boolean,
    [Color.Green]: boolean

【讨论】:

【参考方案5】:

这对我们有用:

type DictionaryFromEnum = 
  [key in keyof typeof SomeEnum]?: string

【讨论】:

【参考方案6】:

使用本机 Record<Keys, Type> 实用程序的简单解决方案。 (Docs)

export enum Colors 
    RED = 'red',
    GREEN = 'green',
    BLUE = 'blue'


export type ColorInterface = Record<Colors, boolean>

这种类型转换为:

// translates to:

export type ColorInterface = 
    red: boolean;
    green: boolean;
    blue: boolean;


重要提示:您必须定义一个enum 键并将值相应地映射到它们,否则,您将获得一个使用枚举的类型/接口index 如下:

export enum Colors 
    'red',
    'green',
    'blue'


export type ColorInterface = Record<Colors, boolean>

// translates to:

export type ColorInterface = 
    0: boolean;
    1: boolean;
    2: boolean;

或者,如果您不想明确定义枚举键或者您只有几个键要使用,您也可以使用 type 别名定义颜色,这也将正确转换为您需要的:

export type Colors = 'red' | 'green' | 'blue'

// will also translate to:

export type ColorInterface = 
    red: boolean;
    green: boolean;
    blue: boolean;


【讨论】:

【参考方案7】:

您可能正在搜索key remapping via as

注意:需要TypeScript ^4.1

例子:

enum Color 
  red,
  blue,
  green,


// Define valid colors
// type TColor = 'red' | 'blue' | 'green';
type TColor = keyof typeof Color;

// Define object structure, with `color` as prefix for each `TColor`
type TWithColorCode = 
  [colorKey in TColor as `color$Capitalize<string & colorKey>`]: string;
;

const a: TWithColorCode = 
  // All properties will be required
  colorGreen: '#00FF00',
  colorBlue: '#0000FF',
  colorRed: '#FF0000',
;

// Extending an `interface`:

export interface ICarRGB extends TWithColorCode 
  id: number;
  name: string;
  // Optional property
  createdAt?: Date;


const b: ICarRGB = 
  id: 1,
  name: 'Foo',
  colorGreen: '#00FF00',
  colorBlue: '#0000FF',
  colorRed: '#FF0000',
;

【讨论】:

以上是关于在打字稿中使用枚举作为接口键的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:如何检查一个值是不是是有效的枚举键值? [复制]

如何在打字稿中键入枚举变量?

使用枚举和泛型在打字稿中获取星期几

在打字稿中扩展枚举

如何在打字稿中访问枚举的名称

字符串枚举类似于打字稿中的类型[重复]