泛型类型防护,包括基元

时间:2018-11-02 18:36:52

标签: javascript typescript

我正在尝试创建通用类型防护,我已经阅读了导致该解决方案的答案:

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>

1 个答案:

答案 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 typeSentinel的类型相关:

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

这有意义吗?希望能有所帮助。祝你好运!