[SOLVED] TypeScript Builder Pattern similar to Java

Issue

I’m trying to implement the Builder Patten similar to Java in TypeScript 4.6.2.
From what I have read, this isn’t the preferred way to do it, but I have some constrains regarding the module exports.

export class HttpRequest {

    static Builder = class {

        private body: string;

        setBody(body: string): HttpRequest.Builder {
            this.body = body;
            return this;
        }

        build(): HttpRequest {
            return new HttpRequest(this);
        }

    }

    private readonly body: string;

    constructor(builder: any) {
        this.body = builder.body;
    }

    getBody(): string {
        return this.body;
    }

}

It seems that the setBody method can’t return a HttpRequest.Builder type, with the following error:

TS2702: 'HttpRequest' only refers to a type, but is being used as a namespace here.

It seems to work fine if // @ts-ignore is present before the method declaration, or if the method signature is changed to setBody(body: string): any.

Is there any way to implement this with nested classes? I’m trying to avoid having two different classes, one for HttpRequest and one for Builder.

Solution

I wouldn’t prefer it to use builder with static classes. You can refer here to access a playground template.

If you want to achieve it in your way do this:

class HttpRequest {

    static Builder = class {

        public body!: string;

        setBody(body: string): typeof HttpRequest.Builder {
            this.body = body;
            return this as any;
        }

        build(): HttpRequest {
            return new HttpRequest(this);
        }

    }

    private readonly body: string;

    constructor(builder: any) {
        this.body = builder.body;
    }

    getBody(): string {
        return this.body;
    }

}

But instead you can practice full pattern with:

interface IHttpRequest
{
 setRequest(body:any):void
}

class HttpRequest implements IHttpRequest
{
  body!:string;
  setRequest(body:string){
    console.log('hook: setRequest called')
    this.body = body;
  }
}

interface IHttpBuilder{
  buildRequest(body:string): void
}

class HttpBuilder implements IHttpBuilder{
  private http = new HttpRequest();
  buildRequest(body:string){
    console.log('hook: buildRequest called')
    this.http.setRequest(body);
  }
}

class Basement{
  private http!: IHttpBuilder;
  constructor(http:IHttpBuilder){
    this.http = http;
  }
  build(body:string){
    console.log('hook: build called')
    this.http.buildRequest(body);
  }
}

let httpReq = new HttpBuilder();
let builder = new Basement(httpReq);

let body = "i am body!";
builder.build(body);

Answered By – Fatih Ersoy

Answer Checked By – Dawn Plyler (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *