Typescript 如何防止使用错误的参数类型调用重载函数
我想为一些JS代码生成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
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
}