Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TypeScript中所有重载参数类型的类型_Typescript - Fatal编程技术网

TypeScript中所有重载参数类型的类型

TypeScript中所有重载参数类型的类型,typescript,Typescript,考虑以下示例: class A { private constructor(public n: number) {} public getDouble() { return this.n * 2; } static from(s: string): A; static from(n: number): A; static from(n1: number, n2: number): A; static from(...args: unknown[]): A {

考虑以下示例:

class A {
  private constructor(public n: number) {}
  public getDouble() {
    return this.n * 2;
  }
  static from(s: string): A;
  static from(n: number): A;
  static from(n1: number, n2: number): A;
  static from(...args: unknown[]): A {
    if (args.length === 1) {
      if (typeof args[0] === 'string') {
        if (args[0].length !== 1) {
          throw new Error('String must have a length of 1')
        }
        return new A(Number(args[0]));
      } else if (typeof args[0] === 'number') {
        if (args[0] > 9) {
          throw new Error('Number must be lower than 10')
        }
        return new A(args[0]);
      }
    } else if (args.length === 2) {
      if (typeof args[0] === 'number' && typeof args[1] === 'number') {
        const sum = args[0] + args[1];
        if (sum > 9) {
          throw new Error('Sum of numbers must be lower than 10')
        }
        return new A(sum);
      }
    }
    throw new Error('No overload matched')
  }
}
A
的实例只能使用来自的静态方法
构造,该方法重载为获取字符串、数字或两个数字。有效参数仅包括长度为1的字符串、小于10的数字以及总和小于10的数字对-其他参数会导致错误

我想实现另一个静态方法
validate
,它将检查
A
的实例是否可以从给定的参数列表中构造,如下所示:

static validate(...args: Parameters<typeof A.from>): boolean {
  try {
    A.from(...args);
    return true;
  } catch (error) {
    return false;
  }
}
type MyOverload<ReturnType> = {
  (s: string): ReturnType;
  (n: number): ReturnType;
  (n1: number, n2: number): ReturnType;
}
静态验证(…参数:参数):布尔值{
试一试{
A.来自(…args);
返回true;
}捕获(错误){
返回false;
}
}
问题是,
Parameters
解析为列表中最后一个重载的参数,在这种情况下,
n1:number,n2:number
,这会导致TypeScript不允许使用任何其他重载签名调用,即
A.validate('foo')

我如何使TypeScript理解可以使用与来自
相同的重载签名调用
验证

我找到了两种可能的解决方案,但都有严重的缺点:

  • 我可以手动构造另一个重载签名来匹配所有以前的重载,并将其放在列表的末尾。然而,这将很难维护,并且会干扰IntelliSense提示
  • 与1类似,但签名将允许
    …args:unknown[]
    。然而,这会使TypeScript认为,当不能使用任何参数时,实际上可以使用任何参数调用
    from
  • 我可以从
  • 重载签名中复制并粘贴所有
    ,并将它们声明为
    验证
    。同样,很难维护-实际用例涉及更多重载以及多个模拟来自
    重载的
    静态方法,这将导致50多行重载声明
    
    还有别的办法解决这个问题吗?有没有办法写一个重载参数类型?

    我找到了一个基于解决方案3的解决方法。我试图找出是否有一种方法可以声明共享同一重载列表的多个成员。这并不漂亮,但我不相信有更优雅的方式来处理这个问题

    解决方案包括将类转换为类型化类表达式,并为重载编写泛型类型。继续问题中的示例,重载类型如下所示:

    static validate(...args: Parameters<typeof A.from>): boolean {
      try {
        A.from(...args);
        return true;
      } catch (error) {
        return false;
      }
    }
    
    type MyOverload<ReturnType> = {
      (s: string): ReturnType;
      (n: number): ReturnType;
      (n1: number, n2: number): ReturnType;
    }
    
    这将实现:

    • 可以使用相同的重载参数列表声明多个方法,但返回类型不同
    • 他们的呼叫签名将正确键入,并与IntelliSense配合使用
    限制(据我所知):

    • 您需要在接口中声明类的公共端,然后在类中重新声明和实现它,并使这两个声明保持同步。这对于重载方法来说显然是一个优势,但对于其他方法来说则不是这样,并且会给维护带来负担
    • 没有受保护的成员,既不是实例也不是静态的(因为接口和类型不能声明私有/受保护的成员)
    • 为重载方法提供额外的参数将很麻烦
    您可以进一步泛化重载类型,以获取额外的参数或多个参数(例如,对于
    createAndMultiplyBy
    )之类的方法:

    类型MyOverload={
    (s:string,arg:MethodArg):返回类型;
    (n:number,arg:MethodArg):返回类型;
    (n1:number,n2:number,arg:MethodArg):返回类型;
    }
    
    然后将方法声明为
    createAndMultiply:MyOverload
    。但是,额外的参数不会得到名称,如果有多个(即
    类型MyOverload
    ),则IntelliSense必须将它们显示为
    MyOverload
    -
    (s:string,…args:[数字,数字])


    在我的用例中,这些额外的重载方法应该只是一个额外的糖分实用程序层。我认为维护这些额外接口的开销不值得,于是放弃了实现它们。

    如果您有一个重载函数/方法,其中每个调用签名都具有相同的返回类型(如
    from()
    的情况,其中返回类型总是
    A
    ),您可以将函数重构为一个版本,其中包含一个rest参数,该参数的类型为:

    这完全可以像以前一样调用:

    A.from("okay"); // works
    A.from(1); // okay
    A.from(2, 4); // okay
    A.from("oops", 2); // error!
    
    事实上,从IntelliSense的角度来看,它甚至看起来像一个重载函数:

    /* A.from(⎀) */
    // 1/3 from(s: string): A
    // 2/3 from(n: number): A
    // 3/3 from(n1: number, n2: number): A
    
    但至关重要的是,
    参数
    现在是元组的完全并集,不会丢失任何信息:

    static validate(...args: Parameters<typeof A.from>): boolean {
      // same impl as before
    }
    

    /* A.from(⎀) */
    // 1/3 from(s: string): A
    // 2/3 from(n: number): A
    // 3/3 from(n1: number, n2: number): A
    
    static validate(...args: Parameters<typeof A.from>): boolean {
      // same impl as before
    }
    
    A.validate("okay"); // works
    A.validate(1); // okay
    A.validate(2, 4); // okay
    A.validate("oops", 2); // error!