我正在尝试创建通用类型防护,我已经阅读了导致该解决方案的答案:
function typeGuard<T>(o, constructor: { new(...args: any[]): T }): o is T {
return o instanceof constructor;
}
这适用于任何具有构造函数的类,例如:
class b {
k: number;
constructor(k: number) {
this.k = k;
}
}
console.log(typeGuard(new b(5), b));
我很难让它在类似这样的环境下工作
console.log(typeGuard(5, number));
或
console.log(typeGuard<number>(5));
我已经尝试过了:
type prim = "string" | "number" | "boolean"; // or without quotes
function typeGuard<T>(o, constructor: { new(...args: any[]): T }): o is T;
function typeGuard<T extends prim>(o): o is T;
function typeGuard<T>(o, constructor?): o is T {
if (constructor) {
return o instanceof constructor;
}
return typeof o ==="string";
}
但是此实现不允许我查看T是什么,并且不能执行类似if typeof o === T
之类的事情。
有没有办法实现这一目标?从理论上讲,我想将string
作为constructor
的{{1}}参数来传递,但这需要typeGuard(5, string)
的类型为:constructor
,但我不需要知道如何在打字稿中实现这一点。
使用示例:
{ new(...args: any[]): T } | Type<string> | Type<number> | Type<boolean>
答案 0 :(得分:1)
我仍然不确定将其作为单个功能的真正需求是什么,但是让我们看看我们可以做什么。您需要在运行时为函数提供一个值,以用于确定是否要检查字符串,数字或其他内容。
让我们说typeGuard()
的第二个参数称为sentinel
,类型为Sentinel
的{{1}},它可以是构造函数,也可以是与{{1 }} 给你。
typeof
然后,给定一个扩展了type TypeofMap = {
string: string,
number: number,
boolean: boolean
}
type Sentinel = (new (...args: any[]) => any) | keyof TypeofMap;
的类型的值,您要保护的类型通过以下conditional type与Sentinel
的类型相关:
Sentinel
您可以像这样实现type GuardedType<T extends Sentinel> = T extends new (...args: any[]) => infer U ?
U : T extends keyof TypeofMap ? TypeofMap[T] : never;
:
typeGuard()
(†请参见Microsoft/TypeScript#13995,了解function typeGuard<T extends Sentinel>(value: any, sentinel: T): value is GuardedType<T> {
// assign to Sentinel instead of generic T to allow type guarding†
const concreteSentinel: Sentinel = sentinel;
if (typeof concreteSentinel === "string") {
return typeof value === concreteSentinel;
} else {
return value instanceof concreteSentinel;
}
}
的原因)
这是您的使用方式:
concreteSentinel
这有意义吗?希望能有所帮助。祝你好运!