Home > Software engineering >  Picking and Instancing a Class using a parameter String with Typescript
Picking and Instancing a Class using a parameter String with Typescript

Time:02-11

It's my first time using TypeScript and using OOP. I've created an interface for a common brokers methods. (Buy, Sell, sell limit, buy limit)

Then i implemented this interface with my brokers API. GBM, Bitso, IB, AmeriTrade and so on i want to instance the correct class through a received string in my end point

example: "/api/broker/:brokername" so i created the following code:

class BrokerIgniter {
    
    private instance: any;

    constructor(broker: string) {

        const brokerClass: any = this.pick(broker);
        if(brokerClass) {
            this.run(brokerClass);
        }
    }

    run(ctor: new () => IExecution | IGBMExecution) {
        this.instance = new ctor();
    }

    pick(className: string) {
        const magicWand: { [K: string]: any } = {
            GBM: GBMBroker,
         };
         if (magicWand[className]) {
            return magicWand[className];
        }
        return null;
    }

    get execute() {
        return this.instance;
    }

}

the "magicWand variable in the pick method contains a list of classes that implements my common interface (in this case there's only one, at the moment..) in my express post method:

const BrokerName = req.params.broker;
if(BrokerName) {
    const Broker = new BrokerIgniter(BrokerName);
    const hash = Broker.execute.createOrderHash('SPXL *', 100, 1);

    super.sendSuccess(res, hash, 'fine');
}

My question is:

Is this a good way to make what i want? there's a name or a pattern for this? can be improved?

If there's a name for this or a pattern can you name it so that i can learn more about it? i've been checking javascript patterns but nothing found related to this.

cheers.

CodePudding user response:

You seem to want to be able to pass in string as the broker key, since this is coming from an API input.

That means you can declare a list of supported classes and their keys outside the BrokerIgniter class, (though a static field would work, too).

// Sort of guessing at your types here since your example is incomplete.
const brokers: Record<
  string,
  typeof IExecution | typeof IGBMExecution | undefined
> = {
  GBM: GBMBroker
}

brokers here is typed to to take any string as an index, and return an IExecution constructor, an IGBMExecution constructor, or undefined if they key has no value.

And now BrokerIgniter can become simply this:

class BrokerIgniter {
    private instance: IExecution | IGBMExecution | undefined;

    constructor(broker: string) {
        const brokerClass = this.pick(broker);
        if(brokerClass) {
            this.run(brokerClass);
        }
    }

    run(ctor: new () => IExecution | IGBMExecution) {
        this.instance = new ctor();
    }

    pick(className: string) {
        return brokers[className] ?? null
    }

    get execute() {
        return this.instance;
    }
}

Playground


That said, this seems like overkill. This is basically the same code.

function igniteBroker(brokerKey: string) {
  const brokerClass = brokers[brokerKey]
  return brokerClass ? new brokerClass() : null
}

And it's a lot simpler. Maybe you intend to expand on the BrokerIgniter class a great deal. But if not, then a simple functional approach will serve you far better.

Playground

  • Related