[英]Casting strings to enum in TypeScript
I've ran into a little issue when working with enums in TypeScript. 在TypeScript中使用枚举时,我遇到了一个小问题。 My scenario is this: 我的情况是这样的:
string
type), and have to cast it to the said enum 我定义了一个方法,该方法可以接受任何传入值( string
类型),并将其强制转换为上述枚举 The problem is that even after checking if the incoming value
from the method, intellisense tells me that value
is still type of string
instead of the enum. 问题是,即使检查了方法中的传入value
,intellisense仍告诉我该value
仍然是string
类型而不是枚举类型。 How can I force value
to be a type of AllowedValues
? 如何强制将value
设为AllowedValues
类型?
Here is a proof-of-concept example: 这是一个概念验证示例:
/** 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`
You can also find it on TypeScript playground . 您也可以在TypeScript操场上找到它。
There are a few things going on here. 这里发生了一些事情。 One is that TypeScript doesn't understand that Object.values(x).includes(y)
is a type guard on y
. 一个是打字稿不明白, Object.values(x).includes(y)
是一种类型的后卫上y
。 It doesn't match the built-in ways that the compiler tries to narrow types, such as typeof
, instanceof
, or in
checks. 它与编译器尝试缩小类型(例如typeof
, instanceof
或in
checks)的内置方式不匹配。 To help the compiler out, you can use a user-defined type guard to express that way of checking: 为了帮助编译器,您可以使用用户定义的类型防护来表示这种检查方式:
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!
}
So let's first change your function to this: 因此,让我们首先将函数更改为此:
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);
}
Uh oh, still not working. 嗯,还是不行。
The second thing going on: if you reassign the value of a variable, TypeScript essentially gives up on its narrowing. 第二件事:如果您重新分配变量的值,TypeScript本质上放弃了它的范围缩小。 The compiler makes a considerable effort to understand the affect of control flow on variable types, but it's not perfect . 编译器付出了相当大的努力来理解控制流对变量类型的影响,但这并不完美 。 So, even though we understand that assigning AllowedValues.LOREM_IPSUM
to value
makes it an AllowedValues
, the compiler gives up and assumes that it is its original annotated type, which is string
. 因此,即使我们知道将AllowedValues.LOREM_IPSUM
分配给value
使其成为AllowedValues
,编译器AllowedValues
放弃并假定它是其原始的带注释类型,即string
。
The way to deal with this is to make a new variable which the compiler understands will never be anything but an AllowedValues
. 处理此问题的方法是创建一个新变量,编译器将其理解为除AllowedValues
任何AllowedValues
。 The most straightforward way to do that is to make it a const
variable, like this: 最简单的方法是使其成为const
变量,如下所示:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}
In the above, the new variable allowedValue
is inferred as an AllowedValues
because it is set as either value
if the type guard succeeds (at which point value
is an AllowedValues
), or AllowedValues.LOREM_IPSUM
if the type guard fails. 在上面的方法中,新变量allowedValue
被推断为AllowedValues
因为如果类型保护成功, AllowedValues
其设置为value
(此时value
是AllowedValues
),如果类型保护失败, AllowedValues.LOREM_IPSUM
其设置为AllowedValues.LOREM_IPSUM
。 Either way, allowedValue
is an AllowedValues
. 无论哪种方式, allowedValue
都是AllowedValues
。
So that would be my suggested change if you want to help the compiler understand things. 因此,如果您想帮助编译器理解事情,那将是我建议的更改。 Hope that helps. 希望能有所帮助。 Good luck! 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.