[英]How to use TS type as a value
I have a TypeScript type which has a bunch of strings and it's defined like this:我有一个 TypeScript 类型,它有一堆字符串,它的定义如下:
type Regions = "" | "eu-west-1" | "eu-east-1" | "us-west-1" | "us-east-1" | "ap-southeast-1" | "ap-east-1"
I then later on in my code get the region from the URL via query-string parameters.然后我稍后在我的代码中通过查询字符串参数从 URL 获取区域。 Let's say that the retrieved region from URL is a variable named
region
假设从 URL 检索到的区域是一个名为
region
的变量
So i'm doing some validation in my code and I want make sure the region
is of the type Regions
.所以我在我的代码中做一些验证,我想确保该
region
是Regions
类型。
So in order to do the validation my code says: if (region in Regions) { doStuff();}
因此,为了进行验证,我的代码说:
if (region in Regions) { doStuff();}
Which would work if Region was a variable with all those regions.如果 Region 是所有这些区域的变量,这将起作用。
However since Regions is a type, it's throwing an error saying: 'Regions' only refers to a type, but is being used as a value here
但是,由于 Regions 是一种类型,因此会抛出错误:
'Regions' only refers to a type, but is being used as a value here
Which I understand why, but how can I achieve what i want to do using or extending the type Regions
我明白为什么,但是如何使用或扩展
type Regions
来实现我想要做的事情
I really don't want to create another object or array of strings, I just want use my existing type to do this validation.我真的不想创建另一个 object 或字符串数组,我只想使用我现有的类型来进行此验证。
I did create an enum like this:我确实创建了一个这样的枚举:
enum RegionsList {
'eu-west-1',
'eu-east-1',
'us-west-1',
'us-east-1',
'ap-southeast-1',
'ap-east-1'
}
and then did region in RegionsList
but this is kinda duplicating my Regions type already, and there has to be a better solution that combines the 2. Any help/suggestions is appreciated.然后
region in RegionsList
但这有点重复了我的 Regions 类型,并且必须有一个更好的解决方案来结合 2。任何帮助/建议表示赞赏。
You can't make a value from a type, but you can infer a type from a value.你不能从一个类型中产生一个值,但你可以从一个值中推断出一个类型。 That implies you should start with some runtime value and have the compiler infer the
Regions
type from it.这意味着您应该从一些运行时值开始,并让编译器从中推断出
Regions
类型。
For example, you can make an array of valid region names:例如,您可以创建一个有效区域名称的数组:
const Regions = ["", "eu-west-1", "eu-east-1", "us-west-1",
"us-east-1", "ap-southeast-1", "ap-east-1"] as const;
type Regions = typeof Regions[number];
You can verify that the type Regions
is the same as in your definition.您可以验证类型
Regions
是否与您的定义中的相同。 Then you can use the array to check that a string is a valid Regions
(such as when you implement a user-defined type guard function ):然后你可以使用数组来检查一个字符串是一个有效的
Regions
(比如当你实现一个用户定义的类型保护 function 时):
function checkRegion(region: string): region is Regions {
return (Regions as readonly string[]).indexOf(region) >= 0;
}
Or, if you want to use in
, you can make an object whose keys are the values you care about, instead of making an array:或者,如果您想使用
in
,您可以创建一个 object ,其键是您关心的值,而不是创建一个数组:
const Regions = {
"": true,
"eu-west-1": true,
"eu-east-1": true,
"us-west-1": true,
"ap-southeast-1": true,
"ap-east-1": true
}
type Regions = keyof typeof Regions;
And again you can verify that Regions
is the right type, and use in
:您可以再次验证
Regions
是正确的类型,并使用in
:
function checkRegion(region: string): region is Regions {
return region in Regions;
}
You could use an enum
as above, but you'd need to be careful, since numeric enums have a reverse mapping and so "0" in RegionsEnum
is true
, possibly surprisingly.您可以使用上面的
enum
,但您需要小心,因为数字枚举具有反向映射,因此"0" in RegionsEnum
为true
,可能令人惊讶。 If you would still rather use that, it could look like this:如果您仍然愿意使用它,它可能看起来像这样:
enum RegionsEnum {
"", "eu-west-1", "eu-east-1", "us-west-1", "ap-southeast-1", "ap-east-1"
}
type Regions = keyof typeof RegionsEnum;
function checkRegion(region: string): region is Regions {
return (region !== (+region) + "") && region in RegionsEnum;
}
(notice the extra bit of code making sure that region
is not a "numeric string"). (请注意确保该
region
不是“数字字符串”的额外代码)。
Okay, hope that helps;好的,希望有帮助; good luck!
祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.