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)