[英]A type guard on literal union types
I have two types in TypeScript:我在TypeScript中有两种类型:
type PublicMethods = 'Time' | 'Assets' | 'AssetPairs' ;
type PrivateMethods = 'Balance' | 'TradeBalance';
I would like to use the same api
function to handle these types, but the behaviour is different for each.我想使用相同的
api
function 来处理这些类型,但每种类型的行为都不同。 Something along the lines of:类似的东西:
public api = (method: PublicMethods | PrivateMethods, params: any) => {
// ...how do I create a type guard here?
if(method instanceof PublicMethods) { // 😱 Doesn't like this!
// ...
}
}
I also tried overloading the function, like this:我还尝试过重载 function,如下所示:
public api(method: PublicMethods | PrivateMethods, params: any, callback: Function);
public api(method: PublicMethods, params: any, callback: Function) {
// ...implementation
}
public api(method: PrivateMethods, params: any, callback: Function) {
// ...implementation
}
Didn't like that either.也不喜欢那样。 Any suggestions?
有什么建议么?
You can create a type guard like this:你可以像这样创建一个类型保护:
const isPublicMethod = (value: any): value is PublicMethod => {
return ['Time', 'Assets', 'AssetPairs'].includes(value);
};
and then use it in your API integration function:然后在您的 API 集成 function 中使用它:
public api = (method: PublicMethods | PrivateMethods, params: any) => {
if(isPublicMethod(method)) {
...
}
}
Warning, Be careful, since TS will not throw if PublicMethod
type is updated and type guard is not.警告,小心,因为如果
PublicMethod
类型更新而类型保护没有更新,TS 将不会抛出。
To handle this better, use the following approach:为了更好地处理这个问题,请使用以下方法:
const PUBLIC_METHODS = ['Time', 'Assets', 'AssetPairs'] as const;
type PublicMethod = typeof PUBLIC_METHODS[number];
const isPublicMethod = (value: any): value is PublicMethod => {
return PUBLIC_METHODS.includes(value);
};
If you define your types based on a constant array:如果您根据常量数组定义类型:
const PublicMethods = ['Time', 'Assets', 'AssetPairs'] as const;
const PrivateMethods = ['Balance', 'TradeBalance'] as const;
type PublicMethods = typeof PublicMethods[number];
type PrivateMethods = typeof PrivateMethods[number];
You'll now be able to use the name PublicMethods
as both a type and a variable that refers to the union of strings and array, respectively.您现在可以将名称
PublicMethods
用作类型和变量,分别引用字符串和数组的联合。 With this, you can create a user-defined type guard using a type predicate :有了这个,您可以使用类型谓词创建用户定义的类型保护:
function isPublicMethod(value: string): value is PublicMethods {
// some sort of assertion is needed because
// it will error that type 'string' is not assignable to type '"Time" | "Assets" | "AssetPairs"'
return PublicMethods.includes(value as any);
}
This allows you to narrow the value to PublicMethods
, the type, by checking if PublicMethods
, the array, includes value
:这允许您通过检查数组
PublicMethods
是否包含value
来将值缩小到类型PublicMethods
:
function doStuff(method: PrivateMethods | PublicMethods) {
if (isPublicMethod(method)) {
method
// ^? PublicMethods
}
}
Note that typescript types are not available at runtime, so请注意,typescript 类型在运行时不可用,因此
if(method instanceof PublicMethods) {
// ...
}
does not work, since method
will actually be a string.不起作用,因为
method
实际上是一个字符串。
So a very basic solution is a switch
.所以一个非常基本的解决方案是
switch
。
public api = (method: PublicMethods | PrivateMethods, params: any) => {
switch(method){
case 'Time': ...
case 'Assets': ...
...
}
}
If you want to discern between PublicMethods
and PrivateMethods
without iterating them, you can use enums:如果你想区分
PublicMethods
和PrivateMethods
而不迭代它们,你可以使用枚举:
enum PublicMethods{
'Time' = 'Time',
'Assets' = 'Assets'
}
public api = (method: PublicMethods | PrivateMethods, params: any) => {
if(method in PublicMethods){
...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.