Typescript抽象类从mixin(class,generic)/mixin(class A,class B | c



我最近遇到了一个问题,无法从其他问题中找出解决方案。所以基本上我想实现的是:

我有很多抽象类,我必须创建更多的抽象类来扩展其他类,比如

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时得到的类型相同。


到代码的游乐场链接

最新更新