在TypeScript中将字符串强制转换为枚举
我在使用TypeScript中的枚举时遇到了一个小问题。我的设想是:在TypeScript中将字符串强制转换为枚举,typescript,intellisense,ecmascript-2017,Typescript,Intellisense,Ecmascript 2017,我在使用TypeScript中的枚举时遇到了一个小问题。我的设想是: 我定义了一个包含允许值的字符串枚举 我已经定义了一个方法,该方法接受任何传入值(类型为stringtype),并且必须将其强制转换为所述枚举 问题是,即使在检查从该方法传入的值之后,intellisense告诉我值仍然是字符串的类型,而不是枚举。如何强制value成为AllowedValues的一种类型 以下是一个概念验证示例: /** enum */ enum AllowedValues { LOREM_IPSU
- 我定义了一个包含允许值的字符串枚举
- 我已经定义了一个方法,该方法接受任何传入值(类型为
type),并且必须将其强制转换为所述枚举string
值
之后,intellisense告诉我值
仍然是字符串
的类型,而不是枚举。如何强制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)
是一个ony
。它与编译器试图缩小类型的内置方式不匹配,例如typeof
、instanceof
或检查中的。要帮助编译器完成此任务,可以使用a来表示这种检查方式:
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!
}
哦,还是不行
第二件事是:如果重新分配变量的值,TypeScript实际上放弃了它的收缩。编译器花了相当大的精力来理解控制流对变量类型的影响,但是。因此,即使我们理解将AllowedValues.LOREM_IPSUM
赋值给value
会使它成为AllowedValues
,编译器也会假设它是其原始的注释类型,即字符串
处理这个问题的方法是创建一个新的变量,编译器知道这个变量除了AllowedValues
之外,永远不会是任何东西。最简单的方法是将其设置为const
变量,如下所示:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}
在上面,新变量allowedValue
被推断为AllowedValues
,因为如果类型保护成功(此时value
是一个AllowedValues
),或者如果类型保护失败,它被设置为value
,或者AllowedValues.LOREM_IPSUM
。无论哪种方式,allowedValue
都是一个allowedValue
因此,如果您想帮助编译器理解一些事情,那么这将是我建议的更改。希望有帮助。祝你好运 const av=Object.keys(AllowedValues).find(k=>AllowedValues[k]==='dolor sir')作为AllowedValues;控制台日志(av);谢谢你的详细回答!现在,这对我来说是有意义的:我不知道如果变量重新分配在任何时候发生,TypeSCript将默认为原始的带注释的类型。
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}