Understanding the Builder Design Pattern in TypeScript
Tags: designpattern, typescript
Published: 2024-04-17 13:32:33

---
title: Understanding the Builder Design Pattern in TypeScript
published: true
description: Dive into the Builder Design Pattern in TypeScript. Learn its pros and cons through an easy-to-follow HTTP request builder example. Perfect for cleaner, flexible code.
tags: designpattern,typescript
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2024-04-17 10:49 +0000
---

Design patterns are shared, repeatable solutions for common issues in software engineering. Let's talk about a popular design pattern called the Builder Design Pattern and explore how to implement it in TypeScript with a practical HTTP request builder example.

## What is the Builder Pattern?

The Builder Pattern is a design pattern that simplifies the creation of complex objects by providing a step-by-step approach to building different types and representations of an object using a consistent construction process. By separating the construction of an object from its representation, the same construction process can create various representations.

## Builder Pattern Concept Code

Let's explore a basic example – a StringBuilder, which constructs a string from words:

```typescript
class StringBuilder {
  private words: string[] = [];

  addWord(word: string): StringBuilder {
    this.words.push(word);
    return this;
  }

  build(): string {
    return this.words.join(' ');
  }
}

// Client code using the builder
const myStringBuilder = new StringBuilder();
const sentence = myStringBuilder.addWord('Hello').addWord('world!').build();

console.log(sentence); // Outputs: Hello world!
```

In this code, our builder is the `StringBuilder` class, containing the `addWord` and `build` methods. The `addWord` method appends a word to the words array. Crucially, it also returns `this`, the builder object itself. This design facilitates the chaining of method calls, promoting readability and compactness.

The `build` method completes the process by joining the words together into a sentence. In the client code, we create the `StringBuilder`, add words to it, and finally use build to get the complete sentence.

## Practical Example: HTTP Request Builder

Let's now see how the Builder Pattern can be applied in TypeScript for building an HTTP request.

```typescript
class HttpRequest {
  method: string;
  url: string;
  body: Record<string, any>;
  headers: HeadersInit;

  constructor() {
    this.body = {};
    this.headers = {};
  }
}

class HttpRequestBuilder {
  httpRequest: HttpRequest;

  constructor() {
    this.httpRequest = new HttpRequest();
  }

  setMethod(method: string): HttpRequestBuilder {
    this.httpRequest.method = method;
    return this;
  }

  setUrl(url: string): HttpRequestBuilder {
    this.httpRequest.url = url;
    return this;
  }

  addBody(key: string, value: any): HttpRequestBuilder {
    this.httpRequest.body[key] = value;
    return this;
  }

  addHeader(name: string, value: string): HttpRequestBuilder {
    this.httpRequest.headers[name] = value;
    return this;
  }

  build(): Request {
    return new Request(this.httpRequest.url, {
      method: this.httpRequest.method,
      headers: this.httpRequest.headers,
      body: JSON.stringify(this.httpRequest.body),
    });
  }
}

let fetchRequest = new HttpRequestBuilder()
  .setMethod('POST')
  .setUrl('https://myapi.com/resource')
  .addHeader('Content-Type', 'application/json')
  .addBody('weather', 'is nice today')
  .build();

console.log(fetchRequest); // Outputs: a `Request` object which can be passed directly to `fetch()`

// Then it can be used using FETCH api:
fetch(fetchRequest)
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(err => console.error('Error:', err));
```

Within this **HTTP request builder**, we're applying the **Builder Design Pattern** to progressively build our request. Notice again the use of this in our builder methods, allowing for the chaining of methods that simplifies the creation process.

Here are some potential benefits and drawbacks of using a Builder Pattern.

### Benefits

1. **Flexibility:** Constructs various representations of objects.
2. **Reduced Duplication:** Mitigates code duplication that arises from numerous constructors.
3. **Easy to Edit:** Adjust the object's construction steps without influencing the object's code.

### Drawbacks:

1. **Code Complexity:** May increase complexity due to new interfaces and classes. (personally, I don't consider this as a drawback)
2. **Limits Validation:** The pattern may struggle with property-specific validations such as mutually exclusive properties.

## Conclusion

The Builder Pattern helps handle complex or multi-step object construction processes in a more readable and maintainable way. Keep in mind it's just one tool amongst many – its implementation should always consider the specific project requirements and circumstances.

Do you use **Builder pattern** in your code? If yes, what are your use cases for it?