在 Typescript 中为接口创建混合
Create a mixin for interfaces in Typescript
interface IBase {
baseProp?: string;
}
class Base implements IBase {
baseProp: string = "baseProp";
}
type AnyClass<T> = new () => T;
interface IClass1 extends IBase {
class1Prop?: string;
}
const Class1Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass1> =>
class extends MixedClasses implements IClass1 {
class1Prop: string = "class1Prop";
};
interface IClass2 extends IBase {
class2Prop?: string;
}
const Class2Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass2> =>
class extends MixedClasses implements IClass2 {
class2Prop: string = "class2Prop";
};
// Mix classes
const mix = <T>(...extensions: Array<(anyClass: any) => AnyClass<T>>) => {
let Composition = Base as AnyClass<IBase>;
for (const ext of extensions) {
Composition = ext(Composition);
}
return Composition as AnyClass<T>;
};
// Here can be any number of classes
const Mixed = mix(Class1Mixin, Class2Mixin);
const mixedInit = new Mixed();
// Now mixedInit is IBase & ICLass1
// and I need that it will be IBase & ICLass1 & ICLass2
console.log(mixedInit.baseProp, mixedInit.class1Prop, mixedInit.class2Prop);
我有一个函数可以将任意数量的 classes 与 Base class 混合在一起。但是我不能混用这些classes 的接口。请告诉我如何改进混合函数类型来做到这一点?
下面的代码是solution.The这个解决方案的实质是联合型转交集type.You关于联合型转交集的问题可以看
interface IBase {
baseProp?: string;
}
class Base implements IBase {
baseProp: string = "baseProp";
}
type AnyClass<T> = new () => T;
interface IClass1 extends IBase {
class1Prop?: string;
}
const Class1Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass1> =>
class extends MixedClasses implements IClass1 {
class1Prop: string = "class1Prop";
};
interface IClass2 extends IBase {
class2Prop?: string;
}
const Class2Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass2> =>
class extends MixedClasses implements IClass2 {
class2Prop: string = "class2Prop";
};
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
// Modified Mix classes
const mix = <T extends Array<(MixedClasses: AnyClass<any>) => AnyClass<any>>>(...extensions: T): AnyClass<UnionToIntersection<InstanceType<ReturnType<T[number]>>>> => {
let Composition = Base as AnyClass<IBase>;
for (const ext of extensions) {
Composition = ext(Composition);
}
return Composition as any;
};
const Mixed = mix(Class1Mixin, Class2Mixin);
const mixedInit = new Mixed();
// Now mixedInit is ICLass1 & ICLass2
console.log(mixedInit.baseProp, mixedInit.class1Prop, mixedInit.class2Prop);
interface IBase {
baseProp?: string;
}
class Base implements IBase {
baseProp: string = "baseProp";
}
type AnyClass<T> = new () => T;
interface IClass1 extends IBase {
class1Prop?: string;
}
const Class1Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass1> =>
class extends MixedClasses implements IClass1 {
class1Prop: string = "class1Prop";
};
interface IClass2 extends IBase {
class2Prop?: string;
}
const Class2Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass2> =>
class extends MixedClasses implements IClass2 {
class2Prop: string = "class2Prop";
};
// Mix classes
const mix = <T>(...extensions: Array<(anyClass: any) => AnyClass<T>>) => {
let Composition = Base as AnyClass<IBase>;
for (const ext of extensions) {
Composition = ext(Composition);
}
return Composition as AnyClass<T>;
};
// Here can be any number of classes
const Mixed = mix(Class1Mixin, Class2Mixin);
const mixedInit = new Mixed();
// Now mixedInit is IBase & ICLass1
// and I need that it will be IBase & ICLass1 & ICLass2
console.log(mixedInit.baseProp, mixedInit.class1Prop, mixedInit.class2Prop);
我有一个函数可以将任意数量的 classes 与 Base class 混合在一起。但是我不能混用这些classes 的接口。请告诉我如何改进混合函数类型来做到这一点?
下面的代码是solution.The这个解决方案的实质是联合型转交集type.You关于联合型转交集的问题可以看
interface IBase {
baseProp?: string;
}
class Base implements IBase {
baseProp: string = "baseProp";
}
type AnyClass<T> = new () => T;
interface IClass1 extends IBase {
class1Prop?: string;
}
const Class1Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass1> =>
class extends MixedClasses implements IClass1 {
class1Prop: string = "class1Prop";
};
interface IClass2 extends IBase {
class2Prop?: string;
}
const Class2Mixin = (MixedClasses: AnyClass<any>): AnyClass<IClass2> =>
class extends MixedClasses implements IClass2 {
class2Prop: string = "class2Prop";
};
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
// Modified Mix classes
const mix = <T extends Array<(MixedClasses: AnyClass<any>) => AnyClass<any>>>(...extensions: T): AnyClass<UnionToIntersection<InstanceType<ReturnType<T[number]>>>> => {
let Composition = Base as AnyClass<IBase>;
for (const ext of extensions) {
Composition = ext(Composition);
}
return Composition as any;
};
const Mixed = mix(Class1Mixin, Class2Mixin);
const mixedInit = new Mixed();
// Now mixedInit is ICLass1 & ICLass2
console.log(mixedInit.baseProp, mixedInit.class1Prop, mixedInit.class2Prop);