【问题标题】: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.

我做错了还是不可能?

【问题讨论】:

    标签: typescript enums


    【解决方案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
    };
    

    【讨论】:

    【解决方案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',
          };
          

          【讨论】:

            猜你喜欢
            • 2019-12-27
            • 2018-09-23
            • 2020-05-09
            • 2020-12-09
            • 2020-01-29
            • 1970-01-01
            • 2019-03-13
            • 1970-01-01
            • 2019-07-09
            相关资源
            最近更新 更多