如何使用 TS 类型作为值

Jim*_*avs 0 javascript validation enums types typescript

我有一个 TypeScript 类型,它有一堆字符串,它的定义如下:

type Regions = "" | "eu-west-1" | "eu-east-1" | "us-west-1" | "us-east-1" | "ap-southeast-1" | "ap-east-1"
Run Code Online (Sandbox Code Playgroud)

然后我稍后在我的代码中通过查询字符串参数从 URL 获取区域。假设从 URL 中检索到的区域是一个名为的变量region

所以我在我的代码中做一些验证,我想确保regionis 的类型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'
}
Run Code Online (Sandbox Code Playgroud)

然后做了,region in RegionsList但这已经有点复制我的 Regions 类型了,必须有一个更好的解决方案,结合 2. 任何帮助/建议表示赞赏。

jca*_*alz 6

您不能从类型中生成值,但可以从值中推断出类型。这意味着您应该从一些运行时值开始,并让编译器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];
Run Code Online (Sandbox Code Playgroud)

您可以验证类型Regions是否与定义中的相同。然后您可以使用数组来检查字符串是否有效Regions(例如当您实现用户定义的类型保护函数时):

function checkRegion(region: string): region is Regions {
  return (Regions as readonly string[]).indexOf(region) >= 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想使用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;
Run Code Online (Sandbox Code Playgroud)

您可以再次验证这Regions是正确的类型,然后使用in

function checkRegion(region: string): region is Regions {
  return region in Regions;
}
Run Code Online (Sandbox Code Playgroud)

可以使用enum如上面,但你必须要小心,因为数字枚举有一个反向映射等等"0" in RegionsEnumtrue,可能是令人惊讶的。如果您仍然更愿意使用它,它可能如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)

(注意确保region不是“数字字符串”的额外代码位)。


好的,希望有帮助;祝你好运!

Playground 链接到代码