Last active
October 31, 2021 20:45
-
-
Save DarkStoorM/df9562e058f0b54bb2fc0ee196171153 to your computer and use it in GitHub Desktop.
TypeScript Inject Mixins from multiple classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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