使用Typescript实现Pure Class Mixins

fra*_*ant 4 typescript typescript2.0

我试图定义一个基于纯类的mixin函数,但是我无法为此类型获得正确的类型签名。

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

export function mixin<A>(myclass: A) {
  return class B extends A {
    newMethod() {
      //stuff
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我需要一种表达A需要成为类的方法。
  • 我还需要表达返回类型,这会产生一些错误,其中包括:

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

附加信息:

  • 这在utils.ts导出的模块内部,以便其他模块可以使用它
  • 所有这些都在我正在编写的库中进行

Nit*_*mer 6

这个问题有一个悬而未决的问题: 允许类从泛型类型参数扩展

现在你可以用这样的方法解决这个问题:

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>;
}
Run Code Online (Sandbox Code Playgroud)

操场上的代码

这是基于这里的代码:extend dynamic Base class with generic throw an error


编辑

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

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>;
}
Run Code Online (Sandbox Code Playgroud)

操场上的代码

然后你可以导出B界面,然后你就可以在任何地方使用它。
这段代码运行良好:

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

let NewA = mixin(A);
let newA = new NewA();
newA.method();
newA.newMethod();
Run Code Online (Sandbox Code Playgroud)

输出:

A.方法
B.新方法


Voj*_*jta 5

我想在TypeScript 2.2中使用mixins

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

我从下面的代码开始,不幸的是,它不起作用

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";
}
Run Code Online (Sandbox Code Playgroud)

最后,我得到了下面的代码,该代码更复杂,但可以按预期工作

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";
}
Run Code Online (Sandbox Code Playgroud)

除了@ bruno-grieder答案,请参见以下链接: