简体   繁体   English

如何使用 TS 类型作为值

[英]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 .所以我在我的代码中做一些验证,我想确保该regionRegions类型。

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 RegionsEnumtrue ,可能令人惊讶。 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!祝你好运!

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM