typescript - 字面量联合类型的类型保护
我在 TypeScript 中有两种类型:
type PublicMethods = 'Time' | 'Assets' | 'AssetPairs' ;
type PrivateMethods = 'Balance' | 'TradeBalance';
我想使用相同的api函数来处理这些类型,但每种类型的行为都不同。大概像这样:
public api = (method: PublicMethods | PrivateMethods, params: any) => {
// ...how do I create a type guard here?
if(method instanceof PublicMethods) { // 😱 Doesn't like this!
// ...
}
}
我也尝试过像这样重载函数:
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
}
那个我也不喜欢。有什么建议吗?
答案#1
你可以这样创建类型保护:
const isPublicMethod = (value: any): value is PublicMethod => {
return ['Time', 'Assets', 'AssetPairs'].includes(value);
};
然后在你的 API 集成函数中使用它:
public api = (method: PublicMethods | PrivateMethods, params: any) => {
if(isPublicMethod(method)) {
...
}
}
警告!请小心,因为如果 PublicMethod 的类型已更新而类型保护没有更新,TS 不会抛出错误。
为更好地处理此问题,请使用以下方法:
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);
};
答案#2
如果你基于一个常量数组定义你的类型:
const PublicMethods = ['Time', 'Assets', 'AssetPairs'] as const;
const PrivateMethods = ['Balance', 'TradeBalance'] as const;
type PublicMethods = typeof PublicMethods[number];
type PrivateMethods = typeof PrivateMethods[number];
你现在可以将名称 PublicMethods 同时用作类型和变量,分别指向字符串和数组的联合类型。有了这个,你可以使用类型谓词创建一个用户定义的类型保护:
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);
}
这允许您通过检查 PublicMethods(数组)是否包含 value 来将值缩小到 PublicMethods 类型:
function doStuff(method: PrivateMethods | PublicMethods) {
if (isPublicMethod(method)) {
method
// ^? PublicMethods
}
}
操场
