繁体   English   中英

使用Typescript实现Pure Class mixins

[英]Implement Pure Class mixins with Typescript

我试图定义一个纯类的mixin函数,但我不能得到这个类型的签名。

目的是提供一个接受任何A类作为参数的函数,并返回一个扩展原始A类的新B类。

export function mixin<A>(myclass: A) {
  return class B extends A {
    newMethod() {
      //stuff
    }
  }
}

正如我所说,我无法弄清楚这一点。

  • 我需要一种方式来表达A需要成为一个班级。
  • 我还需要表达返回类型,它会产生几个错误:

    错误TS4060:导出函数的返回类型具有或正在使用私有名称“B”。

附加信息:

  • 这是在utils.ts模块中导出的,以便其他模块可以使用它
  • 这一切都是在我写作的图书馆的背景下进行的

我想在TypeScript 2.2中使用mixins

  • 抽象基类
  • mixins属性上的装饰器@Parameter
  • 模块 导出 mixin定义( Feature )和mixin应用程序( Derived
  • 生成声明文件"declaration": true tsconfig.json中为"declaration": true

我开始使用以下代码,但遗憾的是它不起作用

export type Constructor<T> = new(...args: any[]) => T;

export abstract class AbstractBase {
    fieldA = "a";
}

export function Feature<T extends Constructor<object>>(Base: T) {
    return class extends Base {
        @Parameter()
        fieldB = "b";
    };
}

export class Derived extends Feature(AbstractBase) {
    fieldC = "c";
}

最后,我最终得到了以下代码,这些代码更复杂但按预期工作

export type Constructor<T> = new(...args: any[]) => T;

export abstract class AbstractBase {
    fieldA = "a";
}

export interface Feature {
    fieldB: string;
}

export function Feature<T extends Constructor<object>>(Base: T): T & Constructor<Feature> {
    class TWithFeature extends Base implements Feature {
        @Parameter()
        fieldB = "b";
    }
    return TWithFeature;
}

export const AbstractBaseWithFeature = Feature(AbstractBase as Constructor<AbstractBase>);

export class Derived extends AbstractBaseWithFeature {
    fieldC = "c";
}

除了@bruno-grieder的答案,请看以下链接:

这个问题存在一个未解决的问题: 允许类从泛型类型参数扩展

现在你可以通过以下方式解决这个问题:

interface Base{}
interface BaseClass<T> {
    new (): T
    readonly prototype: T;
}

function mixin<T extends Base>(baseClass: BaseClass<T>) {
    class B extends (baseClass as BaseClass<Base>) {
        newMethod() { }
    }

    return B as BaseClass<T & B>;
}

游乐场代码

这是基于此处的代码: 扩展动态基类与泛型抛出错误


编辑

您可以为将由新类添加的方法定义接口,例如:

interface B {
    newMethod(): void;
}

function mixin<T extends Base>(baseClass: BaseClass<T>): BaseClass<T & B> {
    class BImpl extends (baseClass as BaseClass<Base>) implements B {
        newMethod() {
            console.log("B.newMethod");
        }
    }

    return BImpl as BaseClass<T & B>;
}

游乐场代码

然后你可以导出B接口,然后你可以在任何地方使用它。
这段代码效果很好:

class A implements Base {
    method() {
        console.log("A.method");
    }
}

let NewA = mixin(A);
let newA = new NewA();
newA.method();
newA.newMethod();

输出:

一个方法
B.newMethod

使用Typescript 2.2.1,我在@Nitzan Tomer解决方案中遇到了(主要是导出和可见性)问题,并且不得不求助于此,我相信它更接近mixin文档并使我的(Webstorm)IDE更智能

mixin.ts

export interface Constructor<T> {
    new( ...args: any[] ): T
}

export interface B {
    newMethod(): void;
}

export const mixin = <T extends Constructor<{}>>( baseClass: T ) =>
    class BImpl extends baseClass implements B {
        newMethod() {
            console.log( "B.newMethod" );
        }
    } as Constructor<B> & T

main.ts

import {B, Constructor, mixin} from './mixin'

class A {
    method() {
        console.log( "A.method" )
    }
}

const AB: (typeof A) & Constructor<B>  = mixin( A )
const ab = new AB()
ab.method()
ab.newMethod()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM