我有一个TypeScript类型,其中有很多字符串,其定义如下:
type Regions = "" | "eu-west-1" | "eu-east-1" | "us-west-1" | "us-east-1" | "ap-southeast-1" | "ap-east-1"
然后我在我的代码中稍后通过查询字符串参数从URL获取区域。假设从URL检索到的区域是一个名为region
因此,我正在代码中进行一些验证,并且我想确保region
的类型为Regions
。
因此,为了进行验证,我的代码说:
if (region in Regions) { doStuff();}
如果Region是所有这些区域中的变量,那将起作用。
但是,因为Regions是一种类型,所以它会抛出一个错误:
'Regions' only refers to a type, but is being used as a value here
我理解为什么,但是如何使用或扩展type Regions
我真的不想创建另一个对象或字符串数组,我只想使用现有的类型来进行此验证。
我确实创建了这样的枚举:
enum RegionsList {
'eu-west-1',
'eu-east-1',
'us-west-1',
'us-east-1',
'ap-southeast-1',
'ap-east-1'
}
,然后执行region in RegionsList
,但这已经在复制我的Regions类型,并且必须有一个结合了2的更好的解决方案。任何帮助/建议都值得赞赏。
答案 0 :(得分:3)
您不能从类型中创建值,但是可以从值中推断类型。这意味着您应该从某个运行时值开始,并让编译器从中推断出Regions
类型。
例如,您可以创建一个有效区域名称的数组:
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];
您可以验证类型Regions
与定义中的相同。然后,您可以使用数组检查字符串是否为有效的Regions
(例如,当您实现user-defined type guard function时):
function checkRegion(region: string): region is Regions {
return (Regions as readonly string[]).indexOf(region) >= 0;
}
或者,如果您想使用in
,则可以创建一个对象,其键是您关心的值,而不是创建数组:
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;
同样,您可以验证Regions
是正确的类型,并使用in
:
function checkRegion(region: string): region is Regions {
return region in Regions;
}
您可以如上所述使用enum
,但是您需要注意,因为数字枚举具有reverse mapping,因此"0" in RegionsEnum
是{ {1}},可能令人惊讶。如果您仍然愿意使用它,它可能看起来像这样:
true
(请注意要确保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;
}
不是“数字字符串”的额外代码)。
好的,希望能有所帮助;祝你好运!