typescript 具有多个动态类型的Type Guard函数

oxcyiej7  于 2023-01-18  发布在  TypeScript
关注(0)|答案(1)|浏览(133)

我想创建一个类型保护函数来检查多个类型。它应该是typeof操作符和instanceof操作符的混合。
我从以下实现开始:

function typeof(obj: any, type: "string"): obj is string;
function typeof(obj: any, type: "number"): obj is number;

我是这样使用它的:

function do(value: any) {

  let str: string = "";
  let num: number = 0;

  if(typeof(value, "string")){
      str = value;
  }
  if(typeof(value, "number")){
      num = value;
  }
}

该函数还应检查对象,例如日期:

let date: Date = null;
if(typeof(value, Date)){
    date = value;
}

我试过:

function typeof<K>(obj: any, type: K): obj is K;

但如果类型为日期,则Typescript仅显示DateConstructor。
我的最终目标是一个可以检查多种类型的函数:

function typeof(obj, ...types:[]): ???

let date: Date = new Date();
//if(typeof value === "number" || value instanceof Date)
if(typeof(value, "number", Date)){
  date = date + value;
}

应该如何定义typeOf函数?

0g0grzrc

0g0grzrc1#

要使字符串正常工作,我们首先需要一个字符串到其各自类型的预定义Map:

type TypeofMap = {
    string: string;
    number: number;
    boolean: boolean;
    symbol: symbol;
    undefined: undefined;
    object: object;
    function: (...args: any[]) => any;
    bigint: bigint;
};

然后我们可以稍后查找正确的类型:

type ToType<T> =
    T extends keyof TypeofMap
        ? TypeofMap[T]
        : T extends new (...args: any[]) => infer R
            ? R
            : T;

我还做了这样的修改,如果T是一个构造函数,那么类型应该是T的一个示例,否则,我不知道其他的东西,所以我将使用T本身作为类型。
下面是typeOf的签名(注意O的大写,不能将函数命名为“typeof”):

declare function typeOf<T extends keyof TypeofMap | {} | null | undefined>(value: any, type: T): value is ToType<T>;

泛型约束看起来很奇怪,因为我希望函数在您尝试为类型传递字符串时自动完成TypeofMap中的键,但它仍然应该允许任何类型。由于{} | null | undefined表示任何可能的值,但与keyof TypeofMap不同,我仍然可以自动完成,并且并集不会减少到只有{} | null | undefined
Playground

相关问题