Utilizing mixins in TypeScript requires providing them with the necessary information for inference. It's important to note that mixins cannot infer information that is not explicitly given, especially in the context of the mixin pattern where combinations occur at the end. TypeScript offers various features that can aid in implementing the mixin pattern effectively. For the recommended approach, check out this resource.
In order to simplify the process, I made adjustments to refer to methods as this.methods.process
or this.methods.getResult
within this pattern.
type Constructor = new (...args: any[]) => {};
type GConstructor<T = {}> = new (...args: any[]) => T;
class MyBase {
constructor() {}
async getResult(a: any) {return a}
}
type MyBaseable = GConstructor<MyBase>
function Promises<TBase extends MyBaseable>(Base: TBase) {
return class PromiseClass extends Base {
async process (...args: any[]): Promise<unknown> {
return await Promise.all(args.map(async (arg) => {
return await this.getResult(arg);
}));
}
};
}
const Mixer = Promises(MyBase);
(async () => {
const myInstance = new Mixer()
const _ = await myInstance.process('a', 'b', 'c')
})()
If you prefer to retain this.methods
, an alternative approach could involve:
class MyBase {
// Include private members
_baseMethods = {
getResult: async (a: any) => {return a}
}
constructor() {}
}
type MyBaseable = GConstructor<MyBase>
function Promises<TBase extends MyBaseable>(Base: TBase) {
return class PromiseClass extends Base {
// Incorporate outermost-mixin as members
methods = {
...this._baseMethods,
process: async (...args: any[]): Promise<unknown> => {
return await Promise.all(args.map(async (arg) => {
return await this._baseMethods.getResult(arg);
}));
}
}
};
}
For live demonstration, visit TS Playground
Further resources on TypeScript mixins:
- Exploring the Mixin Pattern in TypeScript
- Understanding the Mixin Pattern In TypeScript – Part 2