1

The wording of my question might be poor, but I'm trying to extend multiple classes in TypeScript and whenever I instantiate the object, I don't want any of the properties to be undefined. So in my various classes, I assign the variables values, but when I log it, they don't show up. In reading the Typescript docs, they mention using a mixin and that works if I want to access a variable, but all the variables are undefined, even though I defined them.

What I'm looking for is this...

const c = new C();
console.log(c)

Whenever I console log this is what I want to see

"propC1": "C1"
"propA1": "A1"
"propA2": "A2"
"propB1": "B1"
"propB2": "B2"
"myNumber": 1000

Instead I only see

 "propC1": "C1"

Here is the code

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            if (name !== 'constructor') {
                derivedCtor.prototype[name] = baseCtor.prototype[name];
            }
        });
    }); 
}

class Z {
  constructor(public myNumber = 1000){}
}

class A extends Z{
  constructor(...){
    super();
  }
}

class B{
  constructor(...){}
}

interface C extends A, B {}

class C implements A, B{
  public propC1 = "C1";
}

applyMixins (C, [A, B]);

Typescript Playground here

pjpscriv
  • 866
  • 11
  • 20
dragonore
  • 783
  • 2
  • 11
  • 25
  • You need to create a *minimal reproduceable example* please, not a convoluted code dump. This should probably be < 15 LoC. Your applied mixins only copy prototype properties, the constructor is never called so those constructor-assigned properties are never created on the instance. – Jared Smith Mar 15 '21 at 02:00
  • If you `console.log(name)` in your loop you will see that `baseCtor.prototype` only includes `constructor` and does not include `propA1`, etc. – Linda Paiste Mar 15 '21 at 02:13

1 Answers1

1

Okay after much research, one Stackoverflow post accomplished this with a class merger function. stackoverflow merge classes typescipt

type Constructable = new (...args: any[]) => any;

const mergeClasses = <S extends Constructable, T extends Constructable, P extends Constructable>(class1: S, class2: T, class3: P) =>
    <Si extends InstanceType<S> = InstanceType<S>, 
    Ti extends InstanceType<T> = InstanceType<T>,
    Pi extends InstanceType<P> = InstanceType<P>>
    (args1: ConstructorParameters<S>, args2: ConstructorParameters<T>, args3: ConstructorParameters<P>): Si & Ti & Pi => {
        const obj1 = new class1(...args1);
        const obj2 = new class2(...args2);
        const obj3 = new class3(...args3);
        for (const p in obj2) {
            obj1[p] = obj2[p];
        }
        for(const p in obj3){
           obj1[p] = obj3[p];
        }
        return obj1 as Si & Ti & Pi;
 };

 const mergeThis = mergeClasses(A, B, C);
 const D = mergeThis<A, B, C>([],[],[]);
dragonore
  • 783
  • 2
  • 11
  • 25