Typescript 如何防止使用错误的参数类型调用重载函数

Typescript 如何防止使用错误的参数类型调用重载函数,typescript,overloading,Typescript,Overloading,我想为一些JS代码生成typescript定义,这有点尴尬,因为有些类的静态方法与其父类的静态方法同名,但类型签名不同。更多细节和细节 我尝试的解决方案是使用以下通用重载: export class Parent { ... static new(arg1: string): Parent } export class Child extends Parent { ... static new(arg1: number, arg2: number): Child

我想为一些JS代码生成typescript定义,这有点尴尬,因为有些类的静态方法与其父类的静态方法同名,但类型签名不同。更多细节和细节

我尝试的解决方案是使用以下通用重载:

export class Parent {
    ...
    static new(arg1: string): Parent
}

export class Child extends Parent {
    ...
    static new(arg1: number, arg2: number): Child
    static new<T, V>(arg1: T): V
}
导出类父类{
...
静态新建(arg1:string):父级
}
导出类子级扩展父级{
...
静态新建(arg1:number,arg2:number):子级
静态新(arg1:T):V
}

这可能被滥用,因为调用具有任意类型的T的泛型形式,从而导致未定义的行为。有没有办法防止这种情况发生?Typescript坚持使用相同名称的所有重载都具有相同的可见性,因此我不能将通用重载设置为私有重载。但是,如果无法限制对具有固定类型的某个签名的调用,那么我们似乎错过了重载的最佳好处。

无论您如何处理重载签名,TypeScript都决定静态方法将从父类()继承,所以你不能只是扩展一个类并解决这个问题。至少在TS发生变化之前。例如:

namespace Original {
  declare namespace Classes {
    class Parent {
      static method(arg1: string): Parent;
      parentProp: string;
    }

    class Child extends Parent {
      static method(arg1: number, arg2: number): Child;
      static method<T, V>(arg1: T): V;
      childProp: string;
    }
  }

  const child = new Classes.Child();
  const parent = new Classes.Parent();
  const alsoParent: typeof parent = new Classes.Child();

  const childConstructorMethod = Classes.Child.method;
  const parentConstructorMethod = Classes.Parent.method;

  // the following inheritance should hold
  const alsoParentConstructorMethod: typeof parentConstructorMethod = childConstructorMethod;
  // which leads to this even without generics
  alsoParentConstructorMethod("oopsie-daisy");
}
这与原始的基于
类的类型几乎相同。类有一个实例端和一个静态端。在这里,实例端变成一个
接口
,而静态端变成一个导出的
常量
变量,该变量既是一个构造函数(
new():…
),又具有方法。但是在这里,即使实例端继承(我们仍然有
子扩展父扩展
),静态端现在彼此无关。这允许您在子构造函数的方法上选择任何想要的签名

这最终会变得更加冗长,尤其是如果您有生成原始声明的实际TypeScript代码,因为现在您必须找到一种方法来断言生成代码符合后面的声明,而且可能会很混乱。但是,它给了你更多的自由。希望这能有所帮助。祝你好运


TypeScript使类的静态端从父类的静态端继承。这有一系列好的和坏的影响,如果您希望能够在子类构造函数上更改方法的签名,那么您将经历一段糟糕的时光。这里可能有一些详细的声明技巧可以帮助您,但它们并不简单。您真的想要一个名为
new
的静态方法吗?是的,由于GObject C代码的设计方式,伪构造函数作为静态方法在gjs中很常见。我认为这部分是因为C不支持重载函数名,部分是因为大多数其他OOP语言不允许构造函数调用虚拟函数。自然JS构造函数包含在公共API中;起初,我认为这对于您的答案中的聪明方法来说是个问题,但后来我看到您为您的对象提供了
新的
方法,这些方法可以用作构造函数?这是一种非常有趣的方法。目前我正在为别人的项目做贡献,所以我不知道这么大的改变是否对他们有用。目前,它们完全忽略继承,而是在子类中复制父类的属性,因为这种静态方法继承问题在过去给它们带来了问题。我不知道他们是否尝试过类似于我的方法,它有一个我还没有注意到的缺陷。旧版本的评论暗示,他们过去也尝试过接口而不是类,但可能不是使用您扭曲的名称空间。我遇到了一个问题,即伪构造函数被称为
new
:将
new
定义为
new():Child
定义构造函数,而不是静态方法,因此,我无法根据需要使用
const child=child.new()
。但是如果我将它定义为
new:()=>Child
,它就会工作。这两种形式可以同时定义,很好。你也可以做
“new”():Parent(将方法名称用引号括起来)如果您需要编译器将其视为方法(而不是函数值属性…这些基本上是等效的,但编译器在少数情况下确实将方法与函数值属性区分开来)
namespace PossibleFix {
  declare namespace Classes {
    interface Parent {
      parentProp: string;
    }
    export const Parent: {
      method(arg1: string): Parent;
      new (): Parent;
    };

    interface Child extends Parent {
      childProp: string;
    }

    export const Child: {
      method(arg1: number, arg2: number): Child;
      new (): Child;
    };
  }

  const child = new Classes.Child();
  const parent = new Classes.Parent();
  const alsoParent: typeof parent = new Classes.Child();

  const childConstructorMethod = Classes.Child.method;
  const parentConstructorMethod = Classes.Parent.method;

  // now there is no implied inheritance on the static side
  const alsoParentConstructorMethod: typeof parentConstructorMethod = childConstructorMethod;
  //    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ <-- error! not assignable

}