200.Land

factory.ts

The TypeScript code defines two classes, Approach1 and Approach2, both implementing the IApproach interface, which takes IParams as input and returns IOutput. Another class, ServiceThatCombines, also implements IApproach, utilizing a map to dynamically choose between Approach1 and Approach2 based on the type parameter in IParams to execute the do method, facilitating a strategy pattern to determine the approach at runtime.

const enum ApproachTypes {
  Approach1 = "Approach1",
  Approach2 = "Approach2"
}

interface IParams {
  foo: string;
  bar: string;
  type: ApproachTypes;
}

interface IOutput {
  fooBar: string;
  baz: number;
}

interface IApproach {
  params: IParams;
  do(): IOutput;
}

export class Approach1 implements IApproach {
  constructor(public params: IParams) {}
  public do(): IOutput {
    return { baz: 10, fooBar: `${this.params.foo}${this.params.bar}` };
  }
}

export class Approach2 implements IApproach {
  constructor(public params: IParams) {}
  public do(): IOutput {
    return { baz: 20, fooBar: `${this.params.foo}${this.params.bar}` };
  }
}

type Approaches = typeof Approach1 | typeof Approach2;

const approachesMapping = new Map<ApproachTypes, Approaches>([
  [ApproachTypes.Approach1, Approach1],
  [ApproachTypes.Approach2, Approach2]
]);

export class SerivceThatCombines implements IApproach {
  private mappings = approachesMapping;
  private type = this.params.type;
  constructor(public params: IParams) {}
  public do(): IOutput {
    const approach = this.mappings.get(this.type);
    if (approach) {
      return new approach(this.params).do();
    }
    throw new Error(`${this.type} is bollocks`);
  }
}