Home > Blockchain >  How to create a code split typescript module with a constructor using the factory pattern
How to create a code split typescript module with a constructor using the factory pattern

Time:11-01

I have a number of adapters all implemented from an interface like so

export interface IAdapter {
   doSomething(): void;
}

and the implemented classes look very similar and basic to what you'd expect

export default class AdapterA implements IAdapter {
   private _property: string;
   constructor(someProperty: string) {
       this._property = someProperty;
   }
}

I have a factory for the adapters and want to use it somewhat like this

export abstract class AdapterFactory {
    static async getInstance(name: string) Promise<IAdapter> {
        switch(name) {
            case 'a':
                return import('./adapters/adapter-a');
            case 'b':
                return import('./adapters/adapter-b');
        }
    }
}

After the code calling the factory I'd like to be able to use the returned module to instantiate a new instance of the adapter like

const adapterModule = await getInstance('a');
const myNewAdapter = new adapterModule('prop');
myNewAdapter.doSomething();

When I try this within the factory I get:

Type 'typeof import("/[absolute path]/adapters/AdapterA")' provides no match for the signature 'new (someProperty: string): IAdapter'

So I tried adding a definition of new (which I didn't like) like so:

export interface IAdapter {
   new(someProperty: string): IAdapter;
   doSomething(): void;
}

now I get:

This expression is not constructable.

any help anyone can give would be greatly received

CodePudding user response:

The imported constructor should be extracted from default:

const { default: adapterModule } = await getInstance('a');

The reason we need default is that since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of module.exports, it will instead create an artificial namespace object for the CommonJS module.


Not related small suggestions:

  • rename getInstance -> getConstructor
  • change return type to Promise<IAdapterConstructor>

where IAdapterConstructor is:

interface IAdapterConstructor {
  new(someProperty: string): IAdapter;
}
  • Related