TypeScript Mixin 创造的联合类型中,如何支持 prototype 链支持?
type Constructor<T = Record<string, any>> = new (...args: any[]) => T;
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
function Mixin<T extends Constructor[]>(...mixins: T): Constructor<UnionToIntersection<InstanceType<T[number]>>> & UnionToIntersection<T[number]>;
function Mixin<T extends Constructor[]>(...mixins: T) {
class Mix { }
const mergeDesc: any = {};
function copyProperties(target: any, source: any) {
for (let key of Reflect.ownKeys(source)) {
if (key !== 'constructor' && key !== 'prototype' && key !== 'name') {
let desc = Object.getOwnPropertyDescriptor(source, key);
if (desc) {
mergeDesc[key] = mergeDesc[key] || [];
mergeDesc[key].push(desc.value);
Object.defineProperty(target, key, desc);
}
}
}
}
for (let mixin of mixins) {
copyProperties(Mix, mixin); // 拷贝静态属性
copyProperties(Mix.prototype, mixin.prototype); // 拷贝原型属性
}
for (const key in mergeDesc) {
const fns = mergeDesc[key];
Object.defineProperty(Mix.prototype, key, {
configurable: true,
enumerable: true,
writable: true,
value(...args: any[]) {
const context = this;
fns.forEach(function (fn: Function) {
fn.call(context, ...args);
});
},
});
}
return Mix
}
class A {
printA() {
console.log("A");
}
}
class B {
printB(sss: string) {
console.log("B");
}
}
class C extends Mixin(A, B) {
constructor() {
super();
}
printC() {
this.printA();
this.printB('');
}
}
function isInherit(childClass: any, parentClass: any): boolean {
let child = childClass;
while (child) {
if (child === parentClass) {
return true;
}
child = child.__proto__;
}
return false;
}
if (isInherit(C, A)) { // 判定不成立
console.log('C inherit A');
} else {
console.log('C not inherit A');
}
if (isInherit(C, B)) { // 判定不成立
console.log('C inherit B');
} else {
console.log('C not inherit B');
}