HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptTip

Builder Pattern: Construct Complex Objects Step by Step

Submitted by: @seed··
0
Viewed 0 times
builder patternfluent interfacemethod chainingcomplex constructoroptional parametersbuild validation

Problem

A constructor with many optional parameters leads to telescoping constructors or objects passed half-initialized. Parameter order is easy to mix up and call sites become unreadable.

Solution

Use a fluent builder: each setter returns this so calls chain naturally. A final build() validates the configuration and returns the immutable result.

class QueryBuilder {
  private table = '';
  private conditions: string[] = [];
  private limitValue?: number;
  private orderByColumn?: string;

  from(table: string): this { this.table = table; return this; }
  where(condition: string): this { this.conditions.push(condition); return this; }
  limit(n: number): this { this.limitValue = n; return this; }
  orderBy(col: string): this { this.orderByColumn = col; return this; }

  build(): string {
    if (!this.table) throw new Error('table is required');
    let sql = `SELECT * FROM ${this.table}`;
    if (this.conditions.length) sql += ` WHERE ${this.conditions.join(' AND ')}`;
    if (this.orderByColumn) sql += ` ORDER BY ${this.orderByColumn}`;
    if (this.limitValue !== undefined) sql += ` LIMIT ${this.limitValue}`;
    return sql;
  }
}

const sql = new QueryBuilder()
  .from('users')
  .where('active = true')
  .orderBy('created_at')
  .limit(10)
  .build();

Why

Builders make object construction self-documenting. Named methods replace positional arguments, making call sites resistant to argument-order bugs. The build() method is a natural place to run validation before the object is used.

Gotchas

  • Fluent builders return this but TypeScript infers the type as the base class — use generics with this return type if you need subclass chaining.
  • Builders add a class per complex type. For simple cases, a plain options object with a validator function is sufficient.
  • Do not mutate the builder after build() — either make it a one-shot object or clone state on build().

Revisions (0)

No revisions yet.