我在TypeScript中定义了以下enum:

enum Color{
    Red, Green
}

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

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

如何将该值转换为enum?


当前回答

如果你正在处理TypeScript 4.1+和字符串enum,并且你想要一个简单的具有编译时和运行时安全的字符串到enum转换器,下面的工作很好:

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

其他回答

我还遇到了同样的编译器错误。只是Sly_cardinal方法的一个稍短的变种。

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

几乎所有答案都使用不安全的类型转换(as或is)。这一条没有:


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

const colorsMap = new Map<string,Color>(Object.values(Color).map((v) => [v,v]))

function parseColor(volumeData: string): Color | undefined {
    return colorsMap.get(volumeData)
}

const color = parseColor("red")

这个笔记与basarat的回答有关,而不是最初的问题。

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

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

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

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

我不确定是什么导致了这个问题,但我会在这里留下这张便条,以防有人遇到和我一样的问题。

提供的大多数答案都没有对Enums提供广泛的支持。允许OP请求只从字符串值中获取Enum,但是Enum也允许其他值。

interface StandardEnum<T> {
    [id: string]: T | string;
    [nu: number]: string;
}

/**
 * Converts the given representation of the value of one enumerated constant to an equivalent enumerated type.
 *
 * @param type - An enumeration type
 * @param value - A value to convert
 */
export const genericValueToEnum = <T, K extends StandardEnum<T>> (
    type: StandardEnum<T>,
    value: K[keyof K]
): T | undefined => {
    const keys = Object.keys(type); // ...but, not really.
    const values = Object.values(type)
        // Filter enum member names because `Object.values()` includes them.
        .filter((value) => !(
            typeof value === 'string' &&
            keys.includes(value) &&
            type[value] !== value
        ));

    return values.includes(value)
        ? value as unknown as T
        : undefined;
}

这将适用于所有枚举,无论它们多么复杂(或奇怪),只要它们没有被标记。

enum OddEnum {
    None = -1,
    No = 0,
    Yes = 1,
    Twenty = '20'
    Other = 'Other',
    MORE = 'More',
};

genericValueToEnum(OddEnum, -1); // => -1 as OddEnum;
genericValueToEnum(OddEnum, 'Other'); // => 'Other' as OddEnum;
genericValueToEnum(OddEnum, 'MORE'); // => undefined;

如果你正在处理TypeScript 4.1+和字符串enum,并且你想要一个简单的具有编译时和运行时安全的字符串到enum转换器,下面的工作很好:

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