如何在TypeScript中创建返回mixin函数的函数?

时间:2017-07-17 12:53:53

标签: typescript ecmascript-6

我尝试将Polymer.dedupingMixin ES6函数转换为TypeScript。我不确定它是否可能。

https://github.com/Polymer/polymer/blob/v2.0.2/lib/utils/mixin.html

通常,TypeScript 2.2+可以正常使用基本的mixin函数,如下面的代码。



type IConstructable = new (...args: any[]) => object;

function extendClass<T extends IConstructable>(baseClass: T) {
    return class extends baseClass {
        instanceMethod_DynamicClass() { }
        static staticMethod_DynamicClass() { }
    }
}

class Test {
    instanceMethod_TestClass() { }
    static staticMethod_TestClass() { }
}

var d3 = extendClass(Test);
d3.staticMethod_DynamicClass();
d3.staticMethod_TestClass();

var d4 = new d3();
d4.instanceMethod_DynamicClass();
d4.instanceMethod_TestClass();
&#13;
&#13;
&#13;

我尝试创建一些像这个声明功能的函数。

&#13;
&#13;
declare function extendClass<T extends IConstructable>(baseClass: T): {
    new (...args: any[]): {
        instanceMethod_DynamicClass(): void;
    };
    staticMethod_DynamicClass(): void;
} & T;
&#13;
&#13;
&#13;

我的TypeScript代码如下所示。它没有正常工作。我尝试在很多地方修改泛型类型。但它仍然不起作用。

&#13;
&#13;
interface IConstructable<T> {
    new(...args: any[]): T;
}

function extendClass<T extends IConstructable<T>, TExtended extends IConstructable<TExtended>>(mixin: (base: T) => TExtended & T) {
    return function <T, TExtended>(base: T) {
        return mixin(base);
    };
}

class Test {
    instanceMethod_TestClass() { }
    static staticMethod_TestClass() { }
}

class Test2 {
    instanceMethod_TestClass() { }
    static staticMethod_TestClass() { }
}

var propEffect = extendClass(superClass => {    
    return class internalClass extends superClass {
        instanceMethod_ExtendedClass() { }
        static staticMethod_ExtendedClass() { }
    }
});

var d3 = propEffect(Test) ;
d3.staticMethod_ExtendedClass();
d3.staticMethod_TestClass();

var d4 = new d3();
d4.instanceMethod_ExtendedClass();
d4.instanceMethod_TestClass();
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

我不太明白为什么你需要extendClass(),因为它本质上是身份函数(它将一个mixin作为一个参数并返回一个具有相同行为的mixin),你可以实现它像这样,其余的代码没有错误:

function extendClass<M>(mixin: M): M {
  return mixin;
}

假设您需要extendClass()的签名来明确表示它只接受mixins,您可以这样做。为mixin设置一个类型别名是有帮助的:

type Mixin<X extends IConstructable<{}>> = <T extends IConstructable<{}>>(baseClass: T) => T & X;

读:a Mixin<ExtendedClassConstructor>是一个函数,它接受一个通用的基类构造函数并返回一个既是基类构造函数又是ExtendedClassConstructor的函数。

现在您可以按如下方式实施extendClass()

function extendClass<X extends IConstructable<{}>>(mixin: Mixin<X>): Mixin<X> {
  return mixin;
}

不幸的是,当你在箭头函数上调用X时,现在TypeScript不够聪明,无法推断出extendClass()的类型。 X应为internalClass,但您无法参考,因为它不在范围内。您需要定义与internalClass形状相同的适当类型:

type InternalClass = {
  new(...args: any[]): {
    instanceMethod_ExtendedClass(): void;
  }
  staticMethod_ExtendedClass(): void;
}

然后你最终可以调用extendClass(),小心将箭头函数键入为mixin:

var propEffect = extendClass<InternalClass>(<T extends IConstructable<{}>>(superClass: T) => {
  return class internalClass extends superClass {
    instanceMethod_ExtendedClass() { }
    static staticMethod_ExtendedClass() { }
  }
});

这应该与no errors一起使用,虽然我不确定它是否适合您。希望它能帮助你取得进步。