【问题标题】:Convert string to const enum with validation in typescript使用打字稿中的验证将字符串转换为 const 枚举
【发布时间】:2020-10-13 10:27:45
【问题描述】:

我有一个const enum,如下所示:

const enum Color {
    Red = "red",
    Green = "green",
    Blue = "blue"
}

我还有一些来自外部的字符串(比如colorString)。它的值应该是"red",或"green",或"blue",但不确定。我想验证它并在无效值的情况下抛出。

对于“转换”,我可以这样做:

const color: Color = colorString as Color;

这将字符串“转换”为枚举,但不对其进行验证。如果constString === "purple" 在运行时不会出错。为了验证,我可以这样做:

function stringToColor(colorString: string): Color {
    switch (colorString) {
        case Color.Red:
        case Color.Green:
        case Color.Blue:
            return colorString; // no need to do 'as', TS knows that colorString is valid Color enum value
        default:
            throw new Error(`Invalid color ${colorString}.`);
    }
}

这个“转换”字符串为枚举并对其进行验证,但它有点冗长且容易出错。例如,如果我向 Color 枚举添加新值,我必须在 stringToColor 函数中向 switch 添加新的 case 语句,以便我的代码正常运行。

Afaik,常量枚举仅在编译时存在,并在运行时被完全擦除为纯字符串。所以没有任何真正的转换。另外,我不能做Object.values(Color),因为Colorconst enum 并且在运行时不存在。我真正需要的是:

  • 在运行时检查字符串是否具有指定(有效)值之一;
  • 在编译时告诉 TypeScript 字符串可以表示为枚举。

另一种解决方案是将所有有效值保留在这样的对象中:

const colors: { readonly [color in Color]: color } = {
    [Color.Red]: Color.Red,
    [Color.Green]: Color.Green,
    [Color.Blue]: Color.Blue,
};

这里的好处是这个对象必须包含每个枚举值的属性(不像Color[])。如果我向枚举添加一个新值,但忘记将其添加到 colors 对象,如果将在编译时失败。因此,它比写一打case 语句更不容易出错。然后我可以这样做:

function stringToColor(colorString: string): Color | undefined {
    return Object.values(colors).find((value) => colorString === value);
}

如果值无效,则返回undefined,这是可以接受的。

但是,我想知道是否有更简洁和更优雅的解决方案。

【问题讨论】:

    标签: typescript enums


    【解决方案1】:

    如果您在程序中的其他地方使用Color 枚举并且想要坚持使用它,那么不幸的是,对于您正在尝试做的事情没有优雅的解决方案。看看here

    但是,有一种几乎优雅的方法可以实现您想要实现的目标,即使用如下对象:

    const Color = {
        Red: "red",
        Green: "green",
        Blue: "blue"
    } as const
    
    
    const func = (color: typeof Color[keyof typeof Color]) => {
      console.log(color);
    }
    
    func("blue") // okay!
    func("purple") // Argument of type '"purple"' is not assignable to parameter of type '"red" | "green" | "blue"'
    

    缺点是你不能使用Color 作为枚举类型,因为你必须使用typeof Color

    【讨论】:

    • 感谢您的回答,但这不是我想要实现的。我想要实现的是一个函数,它接收一个string(只是一个普通的字符串)并返回一个Color(不管它是Object还是const enum)如果字符串是有效的并抛出如果字符串无效,则返回 undefined。你能提供一个这样的函数的例子吗?你提供的功能不行。
    • @axmrnv 正如我在回答中所写,您想要做的目前无法使用枚举,您必须做出权衡,您可以做的事情:1-编写联合类型和枚举并小心他们总是一致的。 2- 像你一样使用枚举并执行运行时检查 3- 做我在我的 asnwer 中所做的事情。遗憾的是,您的需求没有明确的答案。
    猜你喜欢
    • 2019-10-30
    • 2018-07-05
    • 2018-11-09
    • 2019-03-04
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2010-10-03
    相关资源
    最近更新 更多