在使用TypeScript中的枚举时,我遇到了一个小问题 . 我的情况是这样的:
-
我已经定义了一个包含允许值的字符串枚举
-
我已经定义了一个接受任何传入值(
string
类型)的方法,并且必须将它强制转换为所述枚举
问题是,即使在检查来自方法的传入 value
之后,intellisense告诉我 value
仍然是 string
的类型而不是枚举 . 如何强制 value
成为一种 AllowedValues
?
这是一个概念验证示例:
/** enum */
enum AllowedValues {
LOREM_IPSUM = 'lorem ipsum',
DOLOR_SIT = 'dolor sir',
AMET = 'amet'
}
/** @method */
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
// If value is not found in enum, force it to a default
if (!(Object as any).values(AllowedValues).includes(value))
value = AllowedValues.LOREM_IPSUM;
// Value should be of type `AllowedValues` here
// But TypeScript/Intellisense still thinks it is `string`
console.log(value);
}
doSomething('amet'); // Should log `amet`
doSomething('aloha'); // Should log `lorem ipsum`, since it is not found in `AllowedValues`
你也可以在TypeScript playground找到它 .
1 回答
这里有一些事情发生 . 一个是TypeScript不理解
Object.values(x).includes(y)
在y
上是type guard . 它与编译器尝试缩小类型的内置方式不匹配,例如typeof
,instanceof
或in
检查 . 为了帮助编译器,你可以使用_3001105来表达这种检查方式:所以让我们首先将你的功能改为:
哦,哦,还是不行 .
第二件事:如果你重新分配变量的值,TypeScript基本上放弃了它的缩小 . 编译器花了相当大的努力来理解控制流对变量类型的影响,但it's not perfect . 因此,即使我们理解将
AllowedValues.LOREM_IPSUM
分配给value
使其成为AllowedValues
,编译器gives up并假设它是其原始注释类型,即string
.处理这个的方法是创建一个新的变量,编译器理解它永远不会是
AllowedValues
. 最直接的方法是使它成为const
变量,如下所示:在上面,新变量
allowedValue
被推断为AllowedValues
,因为如果类型保护成功(此时value
是AllowedValues
)它被设置为value
,或者如果类型保护失败则设置为AllowedValues.LOREM_IPSUM
. 无论哪种方式,allowedValue
都是AllowedValues
.如果你想帮助编译器理解事情,那么这将是我建议的更改 . 希望有所帮助 . 祝好运!