B

Builder Pattern

The Builder pattern creates complex objects step by step with a fluent interface.

Code

typescript
1// Product class
2interface HttpRequest {
3 method: "GET" | "POST" | "PUT" | "DELETE";
4 url: string;
5 headers: Record<string, string>;
6 body?: unknown;
7 timeout: number;
8}
9
10// Builder class
11class RequestBuilder {
12 private request: Partial<HttpRequest> = {
13 method: "GET",
14 headers: {},
15 timeout: 5000,
16 };
17
18 setMethod(method: HttpRequest["method"]): this {
19 this.request.method = method;
20 return this;
21 }
22
23 setUrl(url: string): this {
24 this.request.url = url;
25 return this;
26 }
27
28 addHeader(key: string, value: string): this {
29 this.request.headers = {
30 ...this.request.headers,
31 [key]: value,
32 };
33 return this;
34 }
35
36 setBody(body: unknown): this {
37 this.request.body = body;
38 return this;
39 }
40
41 setTimeout(ms: number): this {
42 this.request.timeout = ms;
43 return this;
44 }
45
46 // Type-safe build that requires url
47 build(): HttpRequest {
48 if (!this.request.url) {
49 throw new Error("URL is required");
50 }
51
52 return this.request as HttpRequest;
53 }
54}
55
56// Usage with fluent API
57const getRequest = new RequestBuilder()
58 .setUrl("https://api.example.com/users")
59 .addHeader("Accept", "application/json")
60 .build();
61
62const postRequest = new RequestBuilder()
63 .setMethod("POST")
64 .setUrl("https://api.example.com/users")
65 .addHeader("Content-Type", "application/json")
66 .addHeader("Authorization", "Bearer token123")
67 .setBody({ name: "Alice", email: "alice@example.com" })
68 .setTimeout(10000)
69 .build();
70
71console.log("GET request:", getRequest);
72console.log("POST request:", postRequest);
73
74// Generic builder for any type
75class Builder<T extends object> {
76 private obj: Partial<T> = {};
77
78 set<K extends keyof T>(key: K, value: T[K]): this {
79 this.obj[key] = value;
80 return this;
81 }
82
83 build(): T {
84 return this.obj as T;
85 }
86}
87
88interface User {
89 id: number;
90 name: string;
91 email: string;
92}
93
94const user = new Builder<User>()
95 .set("id", 1)
96 .set("name", "Bob")
97 .set("email", "bob@example.com")
98 .build();
99
100console.log("User:", user);

Run this example locally

$ npx ts-node patterns/builder.ts