ChatGPT解决这个技术问题 Extra ChatGPT

如何在 TypeScript 中将字符串转换为枚举?

我在 TypeScript 中定义了以下枚举:

enum Color{
    Red, Green
}

现在在我的函数中,我将颜色作为字符串接收。我尝试了以下代码:

var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum

如何将该值转换为枚举?

来到这里试图从字符串中获取枚举。枚举 MyEnum { A = 1, B = 5 } 字符串 x = 'B'; MyEnum[x].toString() // 值 5 MyEnum[x] // 值 B 希望对您有所帮助

D
Dave

TypeScript 0.9 中的枚举是基于字符串+数字的。对于简单的转换,您不应该需要类型断言:

enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green];

Try it online

我在我的 OSS 书中有关于这个和其他 Enum 模式的文档:https://basarat.gitbook.io/typescript/type-system/enums


这不适用于 --noImplicitAny(在 VS 中未选中“允许隐式'任何'类型”)。它产生 error TS7017: Index signature of object type implicitly has an 'any' type. 对我来说这有效:var color: Color = (<any>Color)[green];(用 1.4 版测试)
@Vojta 说得对。它在 VS 2012 中不起作用。这个起作用但 var color: Color = (Color)[green];
如果 --noImplicitAny var color : Color = Color[green as keyof typeof Color]; 确保使用它
@Jonas您能否解释或提供文档您的解决方案为何/如何工作?
@Naxos84 看我的回答stackoverflow.com/a/56076148/294242
S
SnailCoil

从 Typescript 2.1 开始,枚举中的字符串键是强类型的。 keyof typeof 用于获取有关可用字符串键 (1) 的信息:

enum Color{
    Red, Green
}

let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";

// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";

// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;

// Works fine
typedColorString = "Red";

// Works fine
const constColorString = "Red";
typedColorString = constColorString

// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;

typedColor = Color[typedColorString];

https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types


所以我们可以使用类型转换:let s = "Green"; let typedColor = <keyof typeof Color> s;
是的,用 const 替换 let 无需强制转换即可。更新示例以澄清这一点。谢谢@SergeyT
typedColorString = Color["Black"]; 现在返回 error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'
单行答案:const color: Color = Color[colorString as keyof typeof Color];
J
Jonas
enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny

此示例适用于 TypeScript 中的 --noImplicitAny

来源:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types


我不知道为什么,但此解决方案不适用于 const enum(使用 Typescript 3.8.3)
@Robin-Hoodie 有点晚了(但为了其他后来者的利益),但是 const 枚举完全是从代码中编译出来的,所以运行时代码没有对枚举键的引用,只有它们的文字值。因此,它无法将这些值映射回枚举键。
这是最好的答案!
只有使无效值的答案undefined
a
alexania

如果您为枚举提供字符串值,则直接转换就可以了。

enum Color {
  Green = "Green",
  Red = "Red"
}

const color = "Green";
const colorEnum = color as Color;

很简单。好的!
这可能会产生误导,因为它不能防止无效颜色。 const colorEnum = "Blue" as Color 不会出错,您会认为 colorEnum 没问题。但如果您要console.log 它,您会看到“蓝色”。 Artru's answer 很好,因为 colorEnum 将是 undefined - 然后您可以专门检查它。
将此与 Object.values(Enum).indexOf(value) >= 0 检查配对,以查看它是否为有效值。
这太棒了!
N
Nick N.

假设您使用打字稿:上面的许多解决方案可能不起作用或过于复杂。

情况:字符串与枚举值不同(大小写不同)

enum Color {
  Green = "green",
  Red = "red"
}

只需使用:

const color = "green" as Color

请注意,这并不能保证有效的枚举。


我想使用枚举的原因之一是限制为有效案例。在此示例中,我可以执行 const color = 'banana' as Color,它仍然可以正常解析,但颜色不再有效。
@DanielWood 这是一个很好的评论,我之前将它添加到我的答案中。
@DanielWood 好点!防止您所说的正确解决方案是什么?
谢谢!你拯救了我的一天。
A
Artur A

打字稿 1.x

如果您确定输入字符串与 Color 枚举完全匹配,请使用:

const color: Color = (<any>Color)["Red"];

如果输入字符串可能与 Enum 不匹配,请使用:

const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
     // TypeScript will understand that mayBeColor is of type Color here
}

Playground

如果我们不将 enum 转换为 <any> 类型,那么 TypeScript 将显示错误:

元素隐式具有“任何”类型,因为索引表达式不是“数字”类型。

这意味着默认情况下,TypeScript Enum 类型适用于数字索引,即 let c = Color[0],但不适用于像 let c = Color["string"] 这样的字符串索引。这是 Microsoft 团队针对更普遍问题的已知限制Object string indexes

打字稿 2.x-4x

TypeScript 移至 keyof typeof 概念。

如果有些使用字符串值枚举:

enum Color {
  Green = "GRN",
  Red = "RD"
}

然后是通过访问枚举成员将键映射到值(Color.Green ->“GRN”)的语言解决方案,但是没有简单的方法来做相反的事情(“GRN” -> Color.Green) .从 reverse-mapping

请记住,字符串枚举成员根本不会生成反向映射。

一种可能的解决方案是手动检查值并将值转换为枚举。请注意,它仅适用于字符串枚举。

function enumFromStringValue<T> (enm: { [s: string]: T}, value: string): T | undefined {
  return (Object.values(enm) as unknown as string[]).includes(value)
    ? value as unknown as T
    : undefined;
}

enumFromStringValue(Color, "RD"); // Color.Red
enumFromStringValue(Color, "UNKNOWN"); // undefined
enumFromStringValue(Color, "Red"); // undefined

您还可以转换为 。 “0”也是错误的输入,但不会返回未定义,所以检查 typeof mayBeColor==='number'
@Quentin2 数字字符串呢?即 typeof '0' 应该是 string
请注意,这不是很安全。 (<any>Color)["hasOwnProperty"] 会起作用,但不是您期望的那样。
@Mat,为什么?为什么它会起作用但不是以预期的方式?
P
Peter Mortensen

我使用以下代码使其工作。

var green= "Green";
var color : Color= <Color>Color[green];

C
Community

此注释与 basarat 的 answer 相关,而不是原始问题。

我在自己的项目中遇到了一个奇怪的问题,编译器给出的错误大致相当于“无法将字符串转换为颜色”,使用此代码的等价物:

var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.

我发现编译器类型推断变得混乱,它认为 colorId 是枚举值而不是 ID。为了解决这个问题,我必须将 ID 转换为字符串:

var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.

我不确定是什么导致了这个问题,但我会在此处留下此说明,以防有人遇到与我相同的问题。


谢谢!这是一个非常愚蠢的问题,很难弄清楚问题是什么。也许 Typescript 应该考虑想出一种更好的方法来处理枚举。
f
ford04

最简单的方法

enum Color { Red, Green }

const c1 = Color["Red"]
const redStr = "Red" // important: use `const`, not mutable `let`
const c2 = Color[redStr]

这适用于 numericstring 枚举。无需使用 type assertion

未知的枚举字符串

const redStrWide: string = "Red" // wide, unspecific typed string
const c3 = Color[redStrWide as keyof typeof Color]
const isEnumName = <T>(str: string, _enum: T): str is Extract<keyof T, string> =>
    str in _enum
const enumFromName = <T>(name: string, _enum: T) => {
    if (!isEnumName(name, _enum)) throw Error() // here fail fast as an example
    return _enum[name]
}
const c4 = enumFromName(redStrWide, Color)

转换字符串枚举值

String enums 没有 reverse mapping(与数字相反)。我们可以创建一个查找助手将枚举值字符串转换为枚举类型:

enum ColorStr { Red = "red", Green = "green" }

const c5_by_name = ColorStr["Red"] // ✅ this works
const c5_by_value_error = ColorStr["red"] // ❌ , but this not

const enumFromValue = <T extends Record<string, string>>(val: string, _enum: T) => {
    const enumName = (Object.keys(_enum) as Array<keyof T>).find(k => _enum[k] === val)
    if (!enumName) throw Error() // here fail fast as an example
    return _enum[enumName]
}

const c5 = enumFromValue("red", ColorStr)

Playground sample


C
Chris

我也遇到了同样的编译器错误。只是 Sly_cardinal 方法的稍微短一些的变化。

var color: Color = Color[<string>colorId];

作为补充:如果您有一个由 javascript 层填充的 typescript 枚举,该层将枚举序列化为字符串(例如通过 AngularJS 的 Asp Web API),您可以执行 myProp.color = Color[<string><any>myProp.color] Cheers
这必须是公认的答案。
P
Peter Mortensen

如果 TypeScript 编译器知道变量的类型是字符串,那么这可以工作:

let colorName : string = "Green";
let color : Color = Color[colorName];

否则,您应该将其显式转换为字符串(以避免编译器警告):

let colorName : any = "Green";
let color : Color = Color["" + colorName];

在运行时,两种解决方案都可以工作。


为什么不直接使用类型转换 <string>colorName 而不是 "" + colorName
s
sgy

我正在寻找可以从 string 获得 enum 的答案,但在我的情况下,枚举值具有不同的字符串值对应项。 OP 有一个简单的 Color 枚举,但我有一些不同的东西:

enum Gender {
  Male = 'Male',
  Female = 'Female',
  Other = 'Other',
  CantTell = "Can't tell"
}

当您尝试使用 "Can't tell" 字符串解析 Gender.CantTell 时,它会返回带有原始答案的 undefined

另一个答案

基本上,我想出了另一个答案,受到 this answer 的强烈启发:

export const stringToEnumValue = <ET, T>(enumObj: ET, str: string): T =>
  (enumObj as any)[Object.keys(enumObj).filter(k => (enumObj as any)[k] === str)[0]];

笔记

我们采用过滤器的第一个结果,假设客户端从枚举中传递了一个有效的字符串。如果不是这种情况,将返回 undefined。

我们将 enumObj 转换为 any,因为使用 TypeScript 3.0+(当前使用 TypeScript 3.5),enumObj 被解析为未知。

使用示例

const cantTellStr = "Can't tell";

const cantTellEnumValue = stringToEnumValue<typeof Gender, Gender>(Gender, cantTellStr);
console.log(cantTellEnumValue); // Can't tell

注意:而且,正如有人在评论中指出的那样,我还想使用 noImplicitAny

更新后的版本

没有强制转换为 any 和正确的类型。

export const stringToEnumValue = <T, K extends keyof T>(enumObj: T, value: string): T[keyof T] | undefined =>
  enumObj[Object.keys(enumObj).filter((k) => enumObj[k as K].toString() === value)[0] as keyof typeof enumObj];

此外,更新后的版本有更简单的调用方式并且更具可读性:

stringToEnumValue(Gender, "Can't tell");

Property 'toString' does not exist on type 'T[K]'.ts(2339)
也许更具可读性:const stringToEnumByValue = <T>(enumObj: Object, value: string): T | undefined => Object.values(enumObj).find((v) => v === value);const stringToEnumByKey = <T>(enumObj: Object, value: string): T | undefined => Object.values(enumObj)[Object.keys(DeliveryState).indexOf(value)];
m
mikeb

我需要知道如何遍历枚举值(正在测试多个枚举的大量排列),我发现这很好用:

export enum Environment {
    Prod = "http://asdf.com",
    Stage = "http://asdf1234.com",
    Test = "http://asdfasdf.example.com"
}

Object.keys(Environment).forEach((environmentKeyValue) => {
    const env = Environment[environmentKeyValue as keyof typeof Environment]
    // env is now equivalent to Environment.Prod, Environment.Stage, or Environment.Test
}

来源:https://blog.mikeski.net/development/javascript/typescript-enums-to-from-string/


这个答案很灵!爱它。尤其是从字符串中创建枚举的方式。这可以在测试枚举或其他情况时为您节省大量输入。
是的,我将它与 Jest 的 each 一起使用,仅用一种方法测试每个枚举案例
P
Peter Mortensen

这个问题中有很多混合信息,所以让我们在 Nick 的在带有 TypeScript 的模型中使用枚举的指南中介绍 TypeScript 2.x+ 的整个实现。

本指南适用于:创建客户端代码的人,这些代码从服务器获取一组已知字符串,这些字符串可以方便地建模为客户端的枚举。

定义枚举

让我们从枚举开始。它应该看起来像这样:

export enum IssueType {
  REPS = 'REPS',
  FETCH = 'FETCH',
  ACTION = 'ACTION',
  UNKNOWN = 'UNKNOWN',
}

这里需要注意两点:

我们明确地将这些声明为字符串支持的枚举案例,这允许我们用字符串而不是其他一些不相关的数字来实例化它们。我们添加了一个在我们的服务器模型上可能存在也可能不存在的选项:未知。如果您愿意,可以将其视为未定义,但我喜欢避免 |尽可能在类型上未定义以简化处理。

拥有 UNKNOWN 案例的好处在于,您可以在代码中非常明显地看到它,并使未知枚举案例的样式呈现亮红色和闪烁,这样您就知道自己没有正确处理某些事情。

解析枚举

您可能正在使用嵌入在另一个模型中的这个枚举,或者单独使用这个枚举,但是您将不得不将来自 JSON 或 XML (ha) 的 string-y 类型枚举解析为您的强类型对应项。当嵌入到另一个模型中时,这个解析器存在于类构造函数中。

parseIssueType(typeString: string): IssueType {
  const type = IssueType[typeString];
  if (type === undefined) {
    return IssueType.UNKNOWN;
  }

  return type;
}

如果枚举被正确解析,它将最终成为正确的类型。否则,它将是 undefined,您可以拦截它并返回您的 UNKNOWN 案例。如果您更喜欢使用 undefined 作为未知情况,则可以返回尝试的枚举解析的任何结果。

从那里开始,只需使用 parse 函数并使用新的强类型变量即可。

const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN

不幸的是,这似乎是不正确的,或者至少是不可推广的。它之所以有效,是因为您的键等于分配给它们的字符串。但是,如果它们(例如我的情况)有所不同,则这是行不通的。用 documentation 的话来说:“请记住,字符串枚举成员根本不会生成反向映射。” 您的代码将编译为类似 IssueType["REPS"]="REPS" 的内容。如果您定义的枚举稍有不同,例如 REPS="reps" 这将产生 IssueType["REPS"]="reps" 这将...
...总是返回 IssueType.UNKNOWN,因为您的枚举中没有键 reps。太糟糕了,我仍然没有找到可行的解决方案,因为我的字符串包含连字符,这使得它们无法用作键。
最后,我在这个 answer 中找到了一个解决方案,让编译器相信这不是字符串枚举。可能值得将此信息编辑为您自己的答案。
u
user3517324

对于 TS 3.9.x

var color : Color = Color[green as unknown as keyof typeof Color];

整洁的!如果没有 as unknown 部分,它似乎也可以工作!
G
Geoff Davids

如果您正在处理 TypeScript 4.1+ 和字符串枚举,并且您想要一个具有编译时和运行时安全性的简单字符串到枚举转换器,那么以下方法效果很好:

export const asEnum = <
  T extends { [key: string]: string },
  K extends keyof T & string
>(
  enumObject: T,
  value: `${T[K]}`
): T[K] => {
  if (Object.values(enumObject).includes(value)) {
    return (value as unknown) as T[K];
  } else {
    throw new Error('Value provided was not found in Enum');
  }
};

enum Test {
  hey = 'HEY',
}

const test1 = asEnum(Test, 'HEY');   // no complaints here
const test2 = asEnum(Test, 'HE');    // compile-time error
const test3 = asEnum(Test, 'HE' as any); // run-time error

O
Ochir Darmaev

枚举

enum MyEnum {
    First,
    Second,
    Three
}

示例使用

const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First 

const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined

忽略区分大小写的解析

class Parser {
    public static parseEnum<T>(value: string, enumType: T): T[keyof T] | undefined {
        if (!value) {
            return undefined;
        }

        for (const property in enumType) {
            const enumMember = enumType[property];
            if (typeof enumMember === 'string') {
                if (enumMember.toUpperCase() === value.toUpperCase()) {
                    const key = enumMember as string as keyof typeof enumType;
                    return enumType[key];
                }
            }
        }
        return undefined;
    }
}

任何像我一样拥有枚举的人都应该将 return enumType[property]; 放在您的枚举项看起来像 Skills = "anyvalue" 的情况下
@neustart47 你能问这个问题吗?
这不是一个问题。我刚刚提到了一些与我搜索相同案例的人的一些变化。你的答案是正确的。
W
Willem van der Veen

以您的方式创建的枚举被编译成一个存储正向 (name -> value) 和反向 (value -> name) 映射的对象。我们可以从这个 chrome devtools 截图中观察到:

https://i.stack.imgur.com/NKVb7.png

这是双重映射如何工作以及如何从一个映射到另一个映射的示例:

enum Color{
    Red, Green
}
// To Number
var greenNr: number = Color['Green'];
console.log(greenNr); // logs 1

// To String
var greenString: string = Color[Color['Green']];  // or Color[Color[1]
console.log(greenString); // logs Green

// In your example

// recieve as Color.green instead of the string green
var green: string = Color[Color.Green];  

// obtain the enum number value which corresponds to the Color.green property
var color: Color = (<any>Color)[green];  

console.log(color); // logs 1

J
Jørgen Andersen

大多数这些答案对我来说似乎过于复杂......

您可以简单地在枚举上创建一个解析函数,该函数期望其中一个键作为参数。添加新颜色后,无需进行其他更改

enum Color { red, green}

// Get the keys 'red' | 'green' (but not 'parse')
type ColorKey = keyof Omit<typeof Color, 'parse'>;

namespace Color {
  export function parse(colorName: ColorKey ) {
    return Color[colorName];
  }
}

// The key 'red' exists as an enum so no warning is given
Color.parse('red');  // == Colors.red

// Without the 'any' cast you would get a compile-time warning
// Because 'foo' is not one of the keys in the enum
Color.parse('foo' as any); // == undefined

// Creates warning:
// "Argument of type '"bar"' is not assignable to parameter of type '"red" | "green"'"
Color.parse('bar');

美丽的解决方案
请注意,此解决方案不适用于字符串枚举。即 enum Color { red = 'R', green = 'G'} Color.parse('R')
F
Flavien Volken

TL;DR:要么:

制作一个解析字符串值并将其转换为枚举的函数。

如果您需要给定值的键名,请不要使用 TS 枚举。

首先,枚举是人类可读的名称和值之间的映射,这就是它的用途。

默认值:默认情况下,TS 将确保您对枚举的已定义键具有唯一值。

这个

enum Color {
    Red, Green
}

相当于

enum Color {
    Red = 0,
    Green = 1
}

两者的转译js代码将是

"use strict";
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
})(Color || (Color = {}));

由于这是不可读的,这是创建后的结果对象:

{0: 'Red', 1: 'Green', Red: 0, Green: 1}

该对象具有字符串和数字属性(不会有任何冲突,因为您不能将枚举键定义为数字)。 TS 足够酷,可以生成一个包含映射键 -> 的对象。值和value -> key

感谢上帝,这是一个双射映射,即每个唯一值都有它的唯一键(因此相反也是如此)

现在麻烦来了,如果我强制使用相同的值怎么办?

enum Color {
    Red = 0,
    Green = 0
}

这是生成的 js 对象

{0: 'Green', Red: 0, Green: 0}

我们不再有双射(这是满射),没有魔法映射0 : ['Green', 'Red']。只有 0 : 'Green',我们失去了 0 : 'Red'

要点:当值为数字时,TS 将始终尝试放置反向映射(值 -> 键)。

现在您可能知道,您还可以在枚举中定义 string values,让我们仅将 Green 值更改为“Green”

enum Color {
    Red = 0,
    Green = "GREEN"
}

这是生成的 js 对象

{0: 'Red', Red: 0, Green: 'GREEN'}

如您所见,Typescript 没有生成映射值 -> 键。它不会因为您最终可能会在值和键名之间发生冲突。请记住:键不能是数字,因此当值是数字时,没有冲突的风险。

这让你明白你不应该依赖枚举的值 -> 键映射。映射可能根本不存在或不准确。

同样,枚举是并且应该仅被视为值的人类可读名称。在 some case 中,ts 甚至根本不会生成任何反向映射。当您定义一个枚举常量时就是这种情况。

一个const enum是一个纯编译时的enum,TS会在transpilation时用它对应的值替换enum的使用

对于 instance

const enum Color {
    Red = 0,
    Green = "GREEN"
}

被转译为

"use strict";

所以只是说……没什么,因为“使用严格”;甚至与我们写的内容无关。

这是使用相同的示例:

const enum Color {
    Red = 0,
    Green = "GREEN"
}
console.log(Color.Green);

被转译为

"use strict";
console.log("GREEN" /* Green */);

如您所见,Color.Green 被转译器替换为“GREEN”。

回到最初的问题,如何将字符串转换为枚举?

解析器解决方案:对不起,我推荐的唯一干净的方法是编写一个函数,使用 switch case 是实现这一点的聪明方法。

function parseColorName(color: string): Color {
  switch (color) {
    case 'Red': return Color.Red;
    case 'Green': return Color.Green;
    default: throw new Error('unknown color');
  }
}

自定义枚举解决方案:

请注意,TS 枚举是不透明的,这意味着编译器无法正确键入值。出于这个原因(尤其是当您需要使用反向映射时),我建议您自己进行枚举,如下所示:

export const ColorType = {
  RED: 'Red',
  GREEN: 'Green',
} as const;

export type ColorType = typeof ColorType[keyof typeof ColorType];

以下是安全的(color 只能采用有效的已知值)。简而言之,您依赖的是字符串联合而不是枚举值。

const color: ColorType= "Green";
// And if you need to create a color from the enum like value:
const anotherColor: ColorType = ColorType.RED;

O
Oyeme

尝试这个

var color : Color = (Color as any)["Green];

这适用于 3.5.3 版本


f
funder7

Typescript 3.9 提案

enum Color{ RED, GREEN }

const color = 'RED' as Color;

简单的...柠檬汁!


这是不安全的,'BANANA' as Color 也会通过
我仍然被否决,提出的问题是:“我怎样才能将该值转换为枚举?”所以这是一个答案,可能不是完美的答案,但在这种情况下,最好明确说明为什么不这样做。有很多解决方案,可能大多数都是好的,具体取决于具体情况。
如果问题是“我如何退出程序”an 答案是“抛出错误并且不捕获它”。然而,这是一个糟糕的答案。这也是类似的,这种方式完全消除了类型系统通过手动覆盖它带来的好处。想象一下,必须调试一个有人在某处使用 'YELLOW' as Color 的系统,但与此同时,黄色已作为颜色被删除。 Typescript 应该能捕捉到这样的错误,但如果你手动覆盖它就不会。
我完全同意@dtech 的观点,可能我对 TS 的了解并没有那么深入,我认为上面的代码可以正确设置所有内容(包括类型)。当我发布它时,据我所知,没有任何其他简单的解决方案。看着这个线程,我可以看到围绕这个主题的一些困惑,在我看来应该更容易。你会如何回答 OP ?
B
Bohdan Ivanchenko

它适用于 TypeScript 4.4.3 TS Playground link

  const stringToEnumValue = <T extends Record<string, string>, K extends keyof T>(
    enumObj: T,
    value: string,
  ): T[keyof T] | undefined =>
    enumObj[
      Object.keys(enumObj).filter(
        (k) => enumObj[k as K].toString() === value,
      )[0] as keyof typeof enumObj
    ];

  enum Color {
    Red = 'red',
    Green = 'green',
  }

  const result1 = stringToEnumValue(Color, 'yellow'); // undefined
  const result2 = stringToEnumValue(Color, 'green'); // Color.Green

  console.log(result1) // undefined = undefined
  console.log(result2) // Color.Green = "green"


J
Joshua

如果您对类型保护感兴趣,否则将是 string (这就是我遇到此问题的方式),这可能对您有用:

enum CurrencyCode {
  cad = "cad",
  eur = "eur",
  gbp = "gbp",
  jpy = "jpy",
  usd = "usd",
}

const createEnumChecker = <T extends string, TEnumValue extends string>(
  enumVariable: { [key in T]: TEnumValue }
) => {
  const enumValues = Object.values(enumVariable);
  return (value: string | number | boolean): value is TEnumValue =>
    enumValues.includes(value);
};

const isCurrencyCode = createEnumChecker(CurrencyCode);

const input: string = 'gbp';

let verifiedCurrencyCode: CurrencyCode | null = null;
// verifiedCurrencyCode = input;
// ^ TypeError: Type 'string' is not assignable to type 'CurrencyCode | null'.

if (isCurrencyCode(input)) {
  verifiedCurrencyCode = input; // No Type Error 🎉
}

解决方案取自此 github issue 讨论通用枚举


A
Anuranjan Srivastav

其他变化可以是

const green= "Green";

const color : Color = Color[green] as Color;

H
Hamed Naeemaei

对于 Typescript >= 4,此代码有效:

enum Color{
    Red, Green
}

// Conversion :
var green= "Green";
var color : Color = green as unknown as Color; 

简洁的回答。 +1
a
andrei.b

如果您使用命名空间来扩展枚举的功能,那么您还可以执行类似的操作

    enum Color {
        Red, Green
    }

    export namespace Color {
      export function getInstance(color: string) : Color {
        if(color == 'Red') {
          return Color.Red;
        } else if (color == 'Green') {
          return Color.Green;
        }
      }
    }

并像这样使用它

  Color.getInstance('Red');