问题
I try to convert Polymer.dedupingMixin
ES6 function to TypeScript. I don't sure it's possible or not.
https://github.com/Polymer/polymer/blob/v2.0.2/lib/utils/mixin.html
Normally, TypeScript 2.2+ can work correctly for basic mixin function like the following code.
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();
I try to create some function like this declaration fuction.
declare function extendClass<T extends IConstructable>(baseClass: T): {
new (...args: any[]): {
instanceMethod_DynamicClass(): void;
};
staticMethod_DynamicClass(): void;
} & T;
My TypeScript code looks like the following code. It doesn't work correctly. I try modify generic type in many places. But it's still not work.
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();
回答1:
I don't quite understand why you need extendClass()
, since it is essentially the identity function (it takes a mixin as a parameter and returns a mixin with the same behavior), and you could implement it like this with no errors in the rest of the code:
function extendClass<M>(mixin: M): M {
return mixin;
}
Assuming you need the signature of extendClass()
to explicitly indicate that it only accepts mixins, you can do so. It helps to have a type alias for mixins:
type Mixin<X extends IConstructable<{}>> = <T extends IConstructable<{}>>(baseClass: T) => T & X;
Read: a Mixin<ExtendedClassConstructor>
is a function which takes a generic base class constructor and returns something which is both a base class constructor and an ExtendedClassConstructor
.
Now you can implement extendClass()
as follows:
function extendClass<X extends IConstructable<{}>>(mixin: Mixin<X>): Mixin<X> {
return mixin;
}
Unfortunately, now TypeScript is not clever enough to infer the type of X
when you call extendClass()
on the arrow function. X
should be internalClass
, but you can't refer to it since it's not in scope. You need to define an appropriate type with the same shape as internalClass
:
type InternalClass = {
new(...args: any[]): {
instanceMethod_ExtendedClass(): void;
}
staticMethod_ExtendedClass(): void;
}
and then you can finally call extendClass()
, being careful to type the arrow function as a mixin:
var propEffect = extendClass<InternalClass>(<T extends IConstructable<{}>>(superClass: T) => {
return class internalClass extends superClass {
instanceMethod_ExtendedClass() { }
static staticMethod_ExtendedClass() { }
}
});
This should all work with no errors, although I'm not sure if it's worth it for you. Hope it helps you make progress.
来源:https://stackoverflow.com/questions/45144854/how-to-create-function-that-returns-mixin-function-in-typescript