Builder Variations in TypeScript
Generic Builder
typescript1class Builder<T> {2 private data: Partial<T> = {};34 set<K extends keyof T>(key: K, value: T[K]): this {5 this.data[key] = value;6 return this;7 }89 build(): T {10 return this.data as T;11 }12}1314const shipment = new Builder<Shipment>()15 .set('sender', senderAddress)16 .set('recipient', recipientAddress)17 .build();
Immutable Builder
typescript1class ImmutableBuilder<T> {2 constructor(private readonly data: Partial<T> = {}) {}34 set<K extends keyof T>(key: K, value: T[K]): ImmutableBuilder<T> {5 return new ImmutableBuilder({ ...this.data, [key]: value });6 }78 build(): T {9 return Object.freeze(this.data) as T;10 }11}
Builder with Validation
typescript1class ValidatingBuilder {2 private errors: string[] = [];34 from(address: Address): this {5 if (!address.postalCode) {6 this.errors.push('Sender postal code required');7 }8 this.data.sender = address;9 return this;10 }1112 build(): Shipment {13 if (this.errors.length > 0) {14 throw new ValidationError(this.errors);15 }16 return new Shipment(this.data);17 }18}
Async Builder
typescript1class AsyncShipmentBuilder {2 async from(address: Address): Promise<this> {3 await this.validateAddress(address);4 this.data.sender = address;5 return this;6 }78 async build(): Promise<Shipment> {9 const rates = await this.fetchRates();10 return new Shipment({ ...this.data, rates });11 }12}1314// Usage15const shipment = await new AsyncShipmentBuilder()16 .then(b => b.from(sender))17 .then(b => b.to(recipient))18 .then(b => b.build());
Summary
| Variant | Benefit |
|---|---|
| Generic | Reusable for any type |
| Immutable | Thread-safe, functional |
| Validating | Fail fast with clear errors |
| Async | Handle async operations |