Skip to content

Instantly share code, notes, and snippets.

@DarkStoorM
Last active October 31, 2021 20:45
Show Gist options
  • Select an option

  • Save DarkStoorM/df9562e058f0b54bb2fc0ee196171153 to your computer and use it in GitHub Desktop.

Select an option

Save DarkStoorM/df9562e058f0b54bb2fc0ee196171153 to your computer and use it in GitHub Desktop.

Revisions

  1. DarkStoorM revised this gist Oct 31, 2021. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions mixins.ts
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,6 @@
    * Applies the implementation of baseConstructors to the derived constructor - injects methods into
    * the given class.
    *
    * NOTICE: the baseConstructors have to be of any[] type
    *
    * @param {{ new (): T }} derivedConstructor Class we want to inject mixins into
    * @param {{ new (): unknown }[]} baseConstructors Array of classes we want to take mixins from
    */
  2. DarkStoorM created this gist Oct 31, 2021.
    63 changes: 63 additions & 0 deletions mixins.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    /* eslint-disable @typescript-eslint/no-non-null-assertion */

    /**
    * Applies the implementation of baseConstructors to the derived constructor - injects methods into
    * the given class.
    *
    * NOTICE: the baseConstructors have to be of any[] type
    *
    * @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