我最近遇到了一个问题,无法从其他问题中找出解决方案。所以基本上我想实现的是:
我有很多抽象类,我必须创建更多的抽象类来扩展其他类,比如
abstract class MyAbstractClass extends Mixin(A, B | C | D)
其中Mixin是来自ts mixer npm包的函数A是一个不会改变的抽象类,它保持不变,但另一个类并不具体。
我尝试了泛型,但没有成功,我尝试创建一个工厂函数,但我不能返回像这样的抽象类
return abstract class MyAbstractClass extends Mixin(A, param){}
只是一个非抽象类。
如果有人能提供答案或为我指明正确的方向,我将不胜感激
编辑:我目前正在做的是:
abstract class Button{
abstract onToggle():void
}
abstract class A{
abstract foo():void
}
abstract class B{
abstract bar():void
}
abstract class ExtendedButtonA extends Mixin(Button, A){}
abstract class ExtendedButtonB extends Mixin(Button, B){}
所以当我上最后一堂课时,我必须这样做:
class FinalButtonA extends ExtendedButtonA{}
class FinalButtonB extends ExtendedButtonB{}
我想做的事:
class FinalButton extends ExtendedButton<A>{}
或者类似的东西。
我的建议是这样写ExtendedButton
工厂函数:
function ExtendedButton<T extends abstract new (...args: any) => InstanceType<T>>(
ctor: T
) {
return Mixin(Button, ctor);
}
这似乎适用于您的示例代码:
abstract class A {
abstract foo(): void
}
abstract class FinalButton extends ExtendedButton(A) { }
function foo(fb: FinalButton) {
fb.foo();
fb.onToggle();
}
我这样做的方式是首先看看当你直接调用Mixin(Button, A)
时会发生什么:
const testA = Mixin(Button, A)
// const testA: Class<any[], Button & A, typeof Button & typeof A, false>
然后将其与通用版本进行比较,在通用版本中,我们传入通用抽象构造签名类型的ctor
值,而不是A
function ExtendedButton<T extends abstract new (...args: any) => object>(
ctor: T
) {
return Mixin(Button, ctor);
}
const testA2 = ExtendedButton(A);
// const testA2: Class<any[], Button & object, typeof Button & typeof A, false>
这里的区别在于,第二个类型参数是Button & object
,而不是所需的Button & A
。为什么?编译器似乎正在将构造函数扩展到其约束abstract new (...args: any) => object
并获取其实例类型,当我们需要A
时,过早地一直扩展到object
。
好吧,如果它要使用这个约束,也许我们可以使约束本身通用,这样它仍然有用。给定一个类似构造函数的类型T
,我们可以使用InstanceType<T>
实用程序类型来表示其实例类型。因此,让我们将object
更改为InstanceType<T>
:
function ExtendedButton<T extends abstract new (...args: any) => InstanceType<T>>(
ctor: T
) {
return Mixin(Button, ctor);
}
幸运的是,它可以编译(有时递归约束不会(,现在调用签名看起来像
// function ExtendedButton<T extends abstract new (...args: any) => InstanceType<T>>(
// ctor: T
// ): Class<any[], Button & InstanceType<T>, typeof Button & T, false>
其中所述第二类型参数为CCD_ 14。让我们试试:
const testA3 = ExtendedButton(A);
// const testA3: Class<any[], Button & A, typeof Button & typeof A, false>
完美,这与我们直接调用Mixin
时得到的类型相同。
到代码的游乐场链接