[英]Convert string to const enum with validation in typescript
I have a const enum
like the following:我有一个像下面这样的
const enum
:
const enum Color {
Red = "red",
Green = "green",
Blue = "blue"
}
I also have some string (say, colorString
), coming from outside.我还有一些字符串(比如
colorString
),来自外面。 Its value is supposed to be either "red"
, or "green"
, or "blue"
, but it's not for sure.它的值应该是
"red"
、 "green"
或"blue"
,但不确定。 I'd like to validate it and throw in case of the invalid value.我想验证它并在无效值的情况下抛出。
For 'conversion', I could do just:对于“转换”,我可以这样做:
const color: Color = colorString as Color;
This 'converts' string to enum, but doesn't validate it.这将“转换”字符串为枚举,但不对其进行验证。 If
constString === "purple"
there will be no error at runtime.如果
constString === "purple"
运行时不会出错。 For validation, I could do:为了验证,我可以这样做:
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}.`);
}
}
This 'converts' string to enum and validates it, but it's kinda verbose and error-prone.这将“转换”字符串为枚举并验证它,但它有点冗长且容易出错。 Eg, if I add new value to the
Color
enum, I'll have to add new case
statement to the switch
in the stringToColor
function in order for my code to operate properly.例如,如果我向
Color
枚举添加新值,则必须向stringToColor
函数中的switch
添加新的case
语句,以便我的代码正常运行。
Afaik, const enums exist only at compile time, and are completely erased to plain strings in runtime. Afaik,const 枚举仅在编译时存在,并在运行时完全擦除为纯字符串。 So there is no any real conversion.
所以没有任何真正的转换。 Plus, I can't do
Object.values(Color)
, because Color
is const enum
and doesn't exist at runtime.另外,我不能做
Object.values(Color)
,因为Color
是const enum
并且在运行时不存在。 What I actually need is:我真正需要的是:
Another solution is to keep all valid values in an object like this:另一种解决方案是将所有有效值保留在一个对象中,如下所示:
const colors: { readonly [color in Color]: color } = {
[Color.Red]: Color.Red,
[Color.Green]: Color.Green,
[Color.Blue]: Color.Blue,
};
The good part here is that this object must contain property for every enum value (unlike Color[]
).这里的好处是这个对象必须包含每个枚举值的属性(与
Color[]
不同)。 If I add a new value to enum, but forget to add it to the colors
object, if will fail at compile time.如果我向 enum 添加一个新值,但忘记将它添加到
colors
对象,则 if 将在编译时失败。 So it's less error-prone, than just writing a dozen of case
statements.因此,与仅编写十几个
case
语句相比,它更不容易出错。 Then I could do:然后我可以这样做:
function stringToColor(colorString: string): Color | undefined {
return Object.values(colors).find((value) => colorString === value);
}
It returns undefined
in case of invalid value, which is acceptable.如果值无效,它返回
undefined
,这是可以接受的。
However, I wonder if there are less verbose and more elegant solutions out there.但是,我想知道是否有更简洁、更优雅的解决方案。
If you're using Color
enum somewhere else in your program and want to stick with using it then unfortunately there's no elegant solution for what you're trying to do.如果您在程序中的其他地方使用
Color
enum 并想坚持使用它,那么不幸的是,对于您想要做的事情没有优雅的解决方案。 take a look at here .看看这里。
But, there is one almost elegant way to achieve what you want to achieve, which is to use an object like below:但是,有一种几乎优雅的方法可以实现您想要实现的目标,即使用如下所示的对象:
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"'
The downside is that you can't use Color
as a type like enums, for that you have to use typeof Color
.缺点是您不能将
Color
用作枚举类型,因为您必须使用typeof Color
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.