【问题标题】:Typescript function to convert string enum member to enum将字符串枚举成员转换为枚举的打字稿函数
【发布时间】:2018-07-05 03:27:34
【问题描述】:

我想用 Typescript 写这样的东西:

export function stringToEnum<T>(enumObj: T, str: string): keyof T {
    return enumObj[str];
}

并按如下方式使用:

enum MyEnum {
  Foo
}

stringToEnum<MyEnum>(MyEnum, 'Foo');

返回的地方

MyEnum.Foo

上面的函数按预期工作......但是打字会抛出错误。对于stringToEnum&lt;MyEnum&gt;(MyEnum, 'Foo'); 中的参数MyEnum,Typescript 抱怨:

“typeof MyEnum”类型的参数不能分配给 输入“我的枚举”

这是有道理的……不幸的是。关于如何解决这个问题的任何想法?

【问题讨论】:

  • 为什么?你的用例是什么?

标签: javascript typescript enums


【解决方案1】:

您的签名有点混乱。如果您打算让该方法返回枚举值,则返回类型应为 T[keyof T]str 参数的类型也应该是 keyof T 以防止您传递无效的字符串,但这将限制您传递字符串文字(或 keyof T 类型的良好类型变量,但不是 string ):

function stringToEnum<T>(enumObj: T, str: keyof T): T[keyof T]

那么要么不指定类型参数,让编译器正确推断类型:

// type: Foo
// value: 0  
const result = stringToEnum(MyEnum, 'Foo');

或者您需要提供typeof MyEnum 作为类型参数:

// type: Foo
// value: 0  
const result = stringToEnum<typeof MyEnum>(MyEnum, 'Foo');

如果你真的希望能够传入任意字符串枚举名称,那么返回类型是一个谎言:应该是T[keyof T] | undefined。如果str 的类型是string 并且您启用了noImplicitAny 编译器选项,您在尝试enumObj[str] 时也会遇到麻烦。

要使泛型函数能够正确处理枚举类型,尤其是在运行时具有反向查找条目的数字枚举,还有更多工作要做。看看ts-enum-utilgithubnpm)的源代码,获取灵感

【讨论】:

    【解决方案2】:

    您可以在本地完成所有操作,而无需编写函数:

    enum Color {
        red,
        green,
        blue
    }
    
    // Enum to string
    const redString: string = Color[Color.red];
    alert(redString);
    
    // String to enum
    const str = 'red';
    const redEnum: Color = Color[str];
    alert(redEnum);
    

    或者你可以玩得开心...

    enum MyEnum {
      Foo,
      Bar
    }
    
    function stringToEnum<ET, T>(enumObj: ET, str: keyof ET): T{
        return enumObj[<string>str];
    }
    
    const val = stringToEnum<typeof MyEnum, MyEnum>(MyEnum, 'Foo');
    
    // Detects that `foo` is a typo
    const val2 = stringToEnum<typeof MyEnum, MyEnum>(MyEnum, 'foo');
    

    【讨论】:

    • 对。不过,有什么办法可以用方法做到这一点吗?
    • 我添加了一个有趣的示例...调用函数比仅使用 MyEnum['Foo'] 要复杂得多。
    • 嘿@Fenton。 TS 编译器在当前 TS 版本中出现 7053 错误,也在您的函数中。 This 解释它。所以最简单的解决方案是:const str: string = 'red'; const redEnum: Color = (&lt;any&gt;Color)[str];
    • 除了我最后的评论:如果你有一个像enum Color { Red = "red"} 这样的枚举,那么const redEnum: Color = (&lt;any&gt;Color)["red"] 将不匹配,因为索引器匹配枚举成员名称。所以只有const redEnum: Color = (&lt;any&gt;Color)["Red"] 可以工作。
    【解决方案3】:
     stringToEnum(MyEnum, 'Foo');
    

    离开泛型,让 typescript 来做。 那是因为存储在 MyEnum 下的类型与 Enum 本身不匹配,而是其值的联合类型:

     enum Test { A, B };
    
     const value: Test /* "A" | "B" */ = Test.A;
    

    【讨论】:

      猜你喜欢
      • 2019-03-04
      • 2019-10-30
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      • 2010-10-03
      • 1970-01-01
      相关资源
      最近更新 更多