While mixins are a really great concept in general, I feel they don't really address the issue of extending two classes in a single one. Rather they enhance one class with a fixed set of extra functionality. Actually I don't think it's possible to extend two different, unrelated classes in a single one. But assuming we accept two minor accomodations we can get pretty close:
- Since the prototype chain is linear, instances of the extended class can only be
instanceof
one of its anchestors (let's say the first).
- Since TypeScript classes can only implement interfaces with statically known members (and no generic type variables) it's not possible to create a
class
extending two others in a generic way. We'll settle for a factory function instead.
Now, take a look at the following function:
type Constructable = new (...args: any[]) => any;
const mergeClasses = <S extends Constructable, T extends Constructable>(class1: S, class2: T) =>
<Si extends InstanceType<S> = InstanceType<S>, Ti extends InstanceType<T> = InstanceType<T>>
(args1: ConstructorParameters<S>, args2: ConstructorParameters<T>): Si & Ti => {
const obj1 = new class1(...args1);
const obj2 = new class2(...args2);
for (const p in obj2) {
obj1[p] = obj2[p];
}
return obj1 as Si & Ti;
};
Calling it will return a factory function that constructs object instances implementing both classes originally passed to mergeClasses
. For example to extend two classes
class MyClassOne {
constructor(param1: number, param2: number) { }
}
class MyClassTwo<F, O> {
constructor(param3: number, param4: number) { }
}
you'd just write the following (omit the type parameters if they're not generic):
const instanceFactory = mergeClasses(MyClassOne, MyClassTwo);
const instance = instanceFactory<MyClassOne, MyClassTwo<number, string>>([1, 2], [3, 4]);
You can also check out the sample code here.
SynchronizatorElement
does not appear in the posted code). To get an answer, a minimal self contained way to reproduce your issue will help – Titian Cernicova-Dragomir