Skip to content

Instantly share code, notes, and snippets.

@46bit
Created January 21, 2020 09:24
Show Gist options
  • Save 46bit/8852ea9d5219228368e1dfd9db4f785e to your computer and use it in GitHub Desktop.
Save 46bit/8852ea9d5219228368e1dfd9db4f785e to your computer and use it in GitHub Desktop.
TypeScript's built-in mixins don't allow the mixin to have a useful constructor. I came across https://github.com/Microsoft/TypeScript/issues/14126#issuecomment-503940323 and wanted to check that it really works. It does!
type ComposableConstructor<T, U> =
[T, U] extends [new (a: infer O1) => infer R1,new (a: infer O2) => infer R2] ? {
new (o: O1 & O2): R1 & R2
} & Pick<T, keyof T> & Pick<U, keyof U> : never
function MixA<T extends new (o: any) => any>(Base: T) {
class MixA extends (Base as new (...a: any[]) => {}) {
a_value: number;
constructor(options: { a_value: number }) {
super(options)
this.a_value = options.a_value;
}
a() {
console.log("a: " + this.a_value)
}
}
return MixA as ComposableConstructor<typeof MixA, T>
}
function MixB<T extends new (o: any) => any>(Base: T) {
class MixB extends (Base as new (...a: any[]) => {}) {
b_value: string;
constructor(options: { b_value: string }) {
super(options)
this.b_value = options.b_value;
}
b() {
console.log("b: " + this.b_value)
}
}
return MixB as ComposableConstructor<typeof MixB, T>
}
class AB extends MixA(MixB(class { })) {
ab_value: string;
constructor(options: { a_value: number, b_value: string, ab_value: string }) {
super(options)
this.ab_value = options.ab_value;
}
ab() {
console.log("ab: " + this.ab_value)
}
}
function main() {
let ab = new AB({ a_value: 77, b_value: "wow", ab_value: "wowwww" });
ab.a();
ab.b();
ab.ab()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment