Skip to content

Instantly share code, notes, and snippets.

@DarkStoorM
Last active October 31, 2021 20:45
Show Gist options
  • Save DarkStoorM/df9562e058f0b54bb2fc0ee196171153 to your computer and use it in GitHub Desktop.
Save DarkStoorM/df9562e058f0b54bb2fc0ee196171153 to your computer and use it in GitHub Desktop.
TypeScript Inject Mixins from multiple classes
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/**
* Applies the implementation of baseConstructors to the derived constructor - injects methods into
* the given class.
*
* @param {{ new (): T }} derivedConstructor Class we want to inject mixins into
* @param {{ new (): unknown }[]} baseConstructors Array of classes we want to take mixins from
*/
export function ApplyMixins<T>(
derivedConstructor: { new (): T },
baseConstructors: { new (): unknown }[]
): void {
baseConstructors.forEach((baseConstructor): void => {
Object.getOwnPropertyNames(baseConstructor.prototype).forEach((name: string): void => {
Object.defineProperty(
derivedConstructor.prototype,
name,
/**
* non-null-assertion is necessary as, presumably, PropertyDescriptor should return a
* value here.
*
* WARNING: this depends on the implementation, so non-null-assertion may not always
* be a desirable solution for each project
*/
Object.getOwnPropertyDescriptor(baseConstructor.prototype, name)!
);
});
});
}
class ClassToTakeMixinsFrom1 {
public methodA(): void {
console.log("Method A");
}
}
class ClassToTakeMixinsFrom2 {
public methodB(): void {
console.log("Method B");
}
}
/*
* --------------------------------------------------------------------------
* Mixins Implementation
* --------------------------------------------------------------------------
*/
export interface ClassToInjectMixinsTo extends ClassToTakeMixinsFrom1, ClassToTakeMixinsFrom2 {}
export class ClassToInjectMixinsTo {}
ApplyMixins(ClassToInjectMixinsTo, [ClassToTakeMixinsFrom1, ClassToTakeMixinsFrom2]);
/* --- */
const test = new ClassToInjectMixinsTo();
//-- methodA and methodB are now available in ClassToInjectMixinsTo
test.methodA();
test.methodB();
//-- Outputs:
// Method A
// Method B
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment