How to inherit multiple classes with typescript?

Viewed 30

This is not duplicates it asks new features and answers about inheritance

I'm trying to inherit multiple classes but also their types what I did was the following :-

In Utils class I created classes function to takes a base class then add the rest of classes methods to the base class properties.

class Utils {
  public static classes = (baseClass: any, ...args: any) => {
    const constructors = [];

    class Class extends baseClass {
      constructor(...opts: any) {
        super();

        for (const arg of args) {
          const props = Object.getOwnPropertyNames(arg.prototype);

          for (const prop of props) {
            if (prop === 'constructor') {
              constructors.push(arg.prototype.constructor);
            } else {
              Class.prototype[prop] = arg.prototype[prop];
            }
          }
        }

        for (const constructor of constructors) {
          Object.assign(Class.prototype, new constructor(...opts));
        }
      }
    }

    return Class;
  };
}

export default Utils;

Now I can use it like this :-

class Example extends Utils.classes(EventEmitter, Class1, Class2, Class3) {
  
}

What I want is that I pass generic multiple dynamic types to this class and add it to classses function as follows :-

class Example extends Utils.classes<typeof events, typeof Class1, typeof Class2, typeof Class3>(EventEmitter, Class1, Class2, Class3) {

}

Now in Utils.classes function I can pass the genrics to it as follows :-

public static classes = <A, ...theResetOfGenerics>(baseClass: A, ...args: theResetOfGenerics) => {
  
}

Is this possible to achieve ?

Edit @captain-yossarian from Ukraine

The new solution was to do the following :-

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type ClassType = new (...args: any[]) => any;

class Utils {
  public static classes<T extends ClassType, R extends T[]>(
    ...classRefs: [...R]
  ): new (...args: any[]) => UnionToIntersection<InstanceType<[...R][number]>> {
    return Utils.merge(class {}, ...classRefs);
  }

  public static merge(derived: ClassType, ...classRefs: ClassType[]) {
    const constructors: any = [];

    class Class extends derived {
      constructor(...opts: any) {
        super();

        for (const arg of classRefs) {
          const props = Object.getOwnPropertyNames(arg.prototype);

          for (const prop of props) {
            if (prop === 'constructor') {
              constructors.push(arg.prototype.constructor);
            } else {
              Class.prototype[prop] = arg.prototype[prop];
            }
          }
        }

        for (const constructor of constructors) {
          Object.assign(Class.prototype, new constructor(...opts));
        }
      }
    }

    return Class as any;
  }
}

export default Utils;

Mixins didn't work I had to extend the derived class in order the code to work, and it did.

Now I'm getting new problem. In Example class I used to create static instance of it by using the following property :-

public static Instance: Example;

but I got an error saying :-

Type 'Example' recursively references itself as a base type

Also I'm facing a new problem the inherited class can't call methods from other inherited classes. so methods in class1 can't call methods in class2, I have to create the static variable in order to use it as follows :-

Example.Instance.fooMethodFromClass1();

Is it possible to make classes methods visible to each other without calling them from parent class?

0 Answers
Related