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;
}
}
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.