在TypeScript中获取枚举名称作为字符串

12
我试图找到一种将枚举名称转换为字符串的方法。如果我有以下的 Response 枚举,如何将“Response”转换或提取为字符串?我的其中一个函数以任何枚举作为输入,并且我需要名称而不是枚举类型来执行其他代码。
enum Response 
{
    No = 0,
    Yes = 1 
}

同时,参考以下链接:https://dev59.com/zWMl5IYBdhLWcg3wzpnV - StriplingWarrior
3
我不感兴趣获取枚举值的字符串值。我试图将枚举本身的实际名称“Response”(在此示例中)转换为字符串。 - jurgen w
4个回答

19
不,你不能将枚举名称转换为字符串,因为类型信息仅在编译期间存储。你必须传递额外的参数,指定你正在使用的枚举。
但是你可以使用方括号将数字枚举值转换为字符串,然后再转换回来:
[Fiddle](链接1)
enum YesNo {
    No = 0,
    Yes = 1, 
}

console.log(YesNo[YesNo.Yes]);
console.log(YesNo[YesNo.No]);
console.log(YesNo["Yes"]);
console.log(YesNo["No"]);
console.log(YesNo[1]);
console.log(YesNo[0]);

这段代码编译后会生成:

var YesNo;
(function (YesNo) {
YesNo[YesNo["No"] = 0] = "No";
YesNo[YesNo["Yes"] = 1] = "Yes";
})(YesNo || (YesNo = {}));
console.log(YesNo[YesNo.Yes]);
console.log(YesNo[YesNo.No]);
console.log(YesNo["Yes"]);
console.log(YesNo["No"]);
console.log(YesNo[1]);
console.log(YesNo[0]);


2
对于其他好奇的人,YesNo [1] 不是索引引用,而是值引用。因此,如果 enum YesNo { No = 0, Yes = 8 } ,那么 console.log(YesNo [8]) 返回 Yes。此外,如果找不到该值,则返回 undefined。如果多个枚举具有相同的值,例如 enum YesNo { No = 8,Yes = 8 } ...它将返回在枚举中定义的最后一个,因此在这种情况下它将返回 Yes - wongz
这似乎不适用于具有字符串值的枚举,只适用于具有数字值的枚举。 - undefined
@JeffreyTillwick,是的,只能是数字。 - undefined

2
Object.keys({ Response })[0]; // 'Response'

这太聪明了,应该被接受的答案! - David Fariña
-1: 好的,很巧妙的技巧,但是...如果你在一行代码中硬编码了类型(Response),那么你不需要将它转换为字符串。挑战在于从传递到函数中的类型之后获取类型名称。这样做行不通:foo=func(Response) ... func getName(obj) { return Object.keys({ obj })[0] - 并且使用 typeof Response 或类似语法也不起作用。除非有更好的解决方案,否则似乎必须将类型名称作为参数传递进去,因为目前看来它无法被推断出来。 - TonyG
@TonyG 获取传递枚举的名称与获取传递变量的名称相同 - 除非您使用我上面发布的技巧并将其作为参数传递,否则您无法这样做,因为您正在传递引用或值。OP想要获取枚举名称的方式,这是唯一的方法。 - Tukkan
@Tukkan:我同意你的观点,并试图取消我的投反对票,但系统不允许我这么做。这并不是 OP 挑战问题的完整解决方案,只是一种关于如何解决问题的部分提示,而不能被接受为实现方案的答案。请查看我的答案,它完全实现了你在此提出的优秀解决方案。 - TonyG

1

@Tukkan提供了正确的答案,但过于模糊难以使用。这里是功能代码,直接响应OP。

enum Options {
    yes,
    no
}
type EnumType = Record<string, any>
function showEnumName(theEnum: EnumType) {
    const enumName = Object.keys(theEnum)[0] ?? ''
    console.log(enumName)
}
showEnumName({ Options })

游乐场链接

注:

  1. 将枚举对象传递到函数中,函数从该对象中派生名称。与 Tukkan 的启发式响应相比,后者要求获取枚举名称的过程必须具有字面枚举对象 - 而不是对它的引用,这正是 OP 和我们大多数人所需的。
  2. 索引 [0] 不是必需的。 更正:这取决于 tsconfig 设置。我进行了修改以避免编译时警告,这可能是好策略,也可能不是,但这超出了本主题的范围。
  3. 为了使其在没有编译时错误的情况下工作,需要对传递到函数中的对象进行类型化。您可以简单地使用 (theEnum:any),但那会允许任何东西进入其中。如果您有一个在将枚举对象传递到此代码之前将其类型化为 'any' 的函数,它将会出错。该对象必须是枚举。更严格的类型化也超出了本主题的范围。
  4. 如果您将函数更改为使用更接近 Tukkan 建议的语法,则会发生以下情况 Playground
function showEnumName(theEnum) {
    const enumName = Object.keys({ theEnum })
    console.log(enumName)
}
showEnumName({ Options })

结果不是"选项",而是"theEnum"。也就是说,正如Tukkan正确指出的那样,它告诉我们包含数据的变量的名称,在函数内部当我们想要传递的枚举的名称时是没有帮助的。

如果您喜欢这个答案,请同时为@Tukkan的答案点赞,让他获得积分。如果没有他的灵感,我无法心安理得地独占积分。


1
怎么样:
MyEnum[MyEnum.option1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接