[英]Casting strings to enum in TypeScript
在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操场上找到它。
这里发生了一些事情。 一个是打字稿不明白, Object.values(x).includes(y)
是一种类型的后卫上y
。 它与编译器尝试缩小类型(例如typeof
, instanceof
或in
checks)的内置方式不匹配。 为了帮助编译器,您可以使用用户定义的类型防护来表示这种检查方式:
function isPropertyValue<T>(object: T, possibleValue: any): possibleValue is T[keyof T] {
return Object.values(object).includes(possibleValue);
}
declare function onlyAcceptAllowedValues(allowedValue: AllowedValues): void;
declare const v: string;
if (isPropertyValue(AllowedValues, v)) {
onlyAcceptAllowedValues(v); // v is narrowed to AllowedValues; it works!
}
因此,让我们首先将函数更改为此:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
if (!(isPropertyValue(AllowedValues, value)))
value = AllowedValues.LOREM_IPSUM;
// TypeScript/Intellisense still thinks it is `string`
console.log(value);
}
嗯,还是不行。
第二件事:如果您重新分配变量的值,TypeScript本质上放弃了它的范围缩小。 编译器付出了相当大的努力来理解控制流对变量类型的影响,但这并不完美 。 因此,即使我们知道将AllowedValues.LOREM_IPSUM
分配给value
使其成为AllowedValues
,编译器AllowedValues
放弃并假定它是其原始的带注释类型,即string
。
处理此问题的方法是创建一个新变量,编译器将其理解为除AllowedValues
任何AllowedValues
。 最简单的方法是使其成为const
变量,如下所示:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}
在上面的方法中,新变量allowedValue
被推断为AllowedValues
因为如果类型保护成功, AllowedValues
其设置为value
(此时value
是AllowedValues
),如果类型保护失败, AllowedValues.LOREM_IPSUM
其设置为AllowedValues.LOREM_IPSUM
。 无论哪种方式, allowedValue
都是AllowedValues
。
因此,如果您想帮助编译器理解事情,那将是我建议的更改。 希望能有所帮助。 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.