[英]Using JavaScript Class Mixins with TypeScript Declaration Files
[英]Is there a way to compose class mixins in TypeScript?
我有一个类mixin的层次结构,可以在纯JavaScript中工作。
const
AsFoo = ( superclass ) => class extends superclass {
get foo(){ return true; }
},
AsFooBar = ( superclass ) => class extends AsFoo( superclass ){
get bar(){ return true; }
},
FooBar = AsFooBar( Object ),
fb = new FooBar();
console.log( fb.foo, fb.bar );
// true, true
但是,当我将它们转换为TypeScript时,我收到了AsFoo( superclass )
的错误。
type Constructor<T = {}> = new ( ...args: any[] ) => T;
interface Foo {
foo: boolean;
}
interface FooBar extends Foo {
bar: boolean;
}
const
AsFoo = <T extends Constructor>( superclass: T ): Constructor<Foo> & T => class extends superclass implements Foo {
get foo(){ return true; }
},
AsFooBar = <T extends Constructor>( superclass: T ): Constructor<FooBar> & T => class extends AsFoo<T>( superclass ) implements FooBar {
get bar(){ return true; }
};
// Type 'Constructor<Foo> & T' is not a constructor function type. ts(2507)
我可以做些什么来使TypeScript使用这种模式吗? 我宁愿不只是// @ts-ignore: ¯\\_(ツ)_/¯
它。
我目前正在使用TypeScript 3.2.4。
export type Constructor<T = {}> = new (...args: any[]) => T;
/* turns A | B | C into A & B & C */
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void)
? I
: never;
/* merges constructor types - self explanitory */
export type MergeConstructorTypes<T extends Array<Constructor<any>>> = UnionToIntersection<InstanceType<T[number]>>;
export function Mixin<T extends Array<Constructor<any>>>(constructors: T): Constructor<MergeConstructorTypes<T>> {
const cls = class {
state = {};
constructor() {
constructors.forEach((c: any) => {
const oldState = this.state;
c.apply(this);
this.state = Object.assign({}, this.state, oldState);
});
}
};
constructors.forEach((c: any) => {
Object.assign(cls.prototype, c.prototype);
});
return cls as any;
}
这是我正在玩一段时间的实现,它还合并了每个类的状态,但随意改变那部分以满足您的需求。
用法如下......
class A {
getName() {
return "hello"
}
}
class B {
getClassBName() {
return "class B name"
}
}
class CombineAB extends Mixin([A, B]) {
testMethod() {
this.getClassBName //is here
this.getName // is here
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.