Skip to content

Instantly share code, notes, and snippets.

@captain-yossarian
Created July 14, 2021 17:15
Show Gist options
  • Select an option

  • Save captain-yossarian/8fe2f2215cd4beeb63d379acc282a449 to your computer and use it in GitHub Desktop.

Select an option

Save captain-yossarian/8fe2f2215cd4beeb63d379acc282a449 to your computer and use it in GitHub Desktop.
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type ClassType = new (...args: any[]) => any;
function Mixin<T extends ClassType, R extends T[]>(...classRefs: [...R]):
new (...args: any[]) => UnionToIntersection<InstanceType<[...R][number]>> {
return merge(class { }, ...classRefs);
}
function merge(derived: ClassType, ...classRefs: ClassType[]) {
classRefs.forEach(classRef => {
Object.getOwnPropertyNames(classRef.prototype).forEach(name => {
// you can get rid of type casting in this way
const descriptor = Object.getOwnPropertyDescriptor(classRef.prototype, name)
if (name !== 'constructor' && descriptor) {
Object.defineProperty(
derived.prototype,
name,
descriptor
);
}
});
});
return derived;
}
class Foo {
foo() { }
}
class Bar {
bar() { }
}
class Baz {
baz() {
console.log('baz');
}
}
class MyClass extends Mixin(Foo, Bar, Baz) { }
const my = new MyClass();
my.foo() // ok
my.bar() // ok
my.baz(); // ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment