The builder pattern helps you create complex objects step-by-step. Using generics makes it flexible for different types.
Builder pattern with generics in Typescript
class Builder<T> { private object: Partial<T> = {}; set<K extends keyof T>(key: K, value: T[K]): this { this.object[key] = value; return this; } build(): T { return this.object as T; } }
Partial<T> means the object can have some or all properties of T.
The set method uses generics to ensure the key and value match the object type.
Person object by setting name and age.interface Person {
name: string;
age: number;
}
const personBuilder = new Builder<Person>();
personBuilder.set('name', 'Alice').set('age', 30);
const person = personBuilder.build();Car object with required properties. Optional properties can be skipped.interface Car {
brand: string;
year: number;
color?: string;
}
const carBuilder = new Builder<Car>();
carBuilder.set('brand', 'Toyota').set('year', 2022);
const car = carBuilder.build();This program builds a House object step-by-step using the builder pattern with generics. It sets windows, doors, and garage presence, then prints the final object.
interface House {
windows: number;
doors: number;
hasGarage: boolean;
}
class Builder<T> {
private object: Partial<T> = {};
set<K extends keyof T>(key: K, value: T[K]): this {
this.object[key] = value;
return this;
}
build(): T {
return this.object as T;
}
}
const houseBuilder = new Builder<House>();
houseBuilder
.set('windows', 4)
.set('doors', 2)
.set('hasGarage', true);
const house = houseBuilder.build();
console.log(house);Using generics keeps the builder flexible and type-safe for any object shape.
The Partial<T> type allows building the object piece by piece.
Always call build() to get the final object.
The builder pattern helps create complex objects step-by-step.
Generics make the builder reusable for different object types.
TypeScript ensures keys and values match the object properties.
Practice
What is the main advantage of using the builder pattern with generics in TypeScript?
Solution
Step 1: Understand builder pattern purpose
The builder pattern helps create complex objects step-by-step, improving clarity and flexibility.Step 2: Role of generics in TypeScript
Generics allow the builder to work with any object type while keeping type safety, ensuring keys and values match.Final Answer:
It allows creating different object types step-by-step with type safety. -> Option CQuick Check:
Builder + generics = flexible, safe object creation [OK]
- Thinking builder auto-generates UI
- Believing it skips type checks
- Confusing builder with replacing functions
Which of the following is the correct syntax to declare a generic builder class in TypeScript?
class Builder<T> {
private obj: T;
constructor() {
this.obj = {} as T;
}
set(key: keyof T, value: T[keyof T]): this {
this.obj[key] = value;
return this;
}
build(): T {
return this.obj;
}
}Solution
Step 1: Check generic class declaration
class Builder<T> { private obj: T; constructor() { this.obj = {} as T; } } correctly declares a generic class with<T>and initializesobjas{} as T.Step 2: Identify incorrect initializations
class Builder<T> { private obj: T; constructor() { this.obj = new T(); } } triesnew T()which is invalid in TypeScript. class Builder { private obj: T; constructor() { this.obj = {} as T; } } misses generic<T>. class Builder<T> { private obj: any; constructor() { this.obj = {}; } } usesanylosing type safety.Final Answer:
class Builder<T> { private obj: T; constructor() { this.obj = {} as T; } } -> Option AQuick Check:
Generic class with{} as Tinit = class Builder<T> { private obj: T; constructor() { this.obj = {} as T; } } [OK]
{} as T to initialize generic object safely [OK]- Trying to instantiate generic type with new
- Forgetting to declare generic parameter <T>
- Using any instead of generic type
What will be the output of this code?
class Builder<T> {
private obj: T;
constructor() { this.obj = {} as T; }
set(key: keyof T, value: T[keyof T]): this {
this.obj[key] = value;
return this;
}
build(): T { return this.obj; }
}
interface Person { name: string; age: number; }
const person = new Builder<Person>()
.set('name', 'Alice')
.set('age', 30)
.build();
console.log(person);Solution
Step 1: Understand builder usage
The builder sets 'name' to 'Alice' and 'age' to 30 on an empty object typed as Person.Step 2: Check final build output
Thebuild()method returns the object with both properties set, so output is{ name: 'Alice', age: 30 }.Final Answer:
{ name: 'Alice', age: 30 } -> Option AQuick Check:
Builder sets keys correctly = { name: 'Alice', age: 30 } [OK]
- Expecting partial object missing keys
- Thinking assignment causes error
- Assuming empty object returned
Identify the error in this builder class and select the fix:
class Builder<T> {
private obj: T;
constructor() { this.obj = {}; }
set(key: keyof T, value: T[keyof T]): this {
this.obj[key] = value;
return this;
}
build(): T { return this.obj; }
}Solution
Step 1: Identify initialization error
Assigning{}directly toobj: Tcauses a type error because {} is not guaranteed to be T.Step 2: Correct initialization with type assertion
Using{} as Ttells TypeScript to treat empty object as type T safely during construction.Final Answer:
Initialize obj as{} as Tin constructor. -> Option DQuick Check:
Use{} as Tto fix generic object init [OK]
{} as T to initialize generic objects [OK]- Assigning {} directly without assertion
- Changing key type to string loses type safety
- Removing generics breaks flexibility
You want to build a generic builder that only allows setting properties defined in the object type and prevents setting undefined keys. Which TypeScript feature helps enforce this at compile time?
Solution
Step 1: Understand key restriction need
To prevent setting keys not in the object type, the key parameter must be limited to valid keys.Step 2: Use
keyof Tfor key typekeyof Trepresents all valid keys of type T, so using it restricts keys to only those defined in T.Final Answer:
Usingkeyof Tas the key type in thesetmethod. -> Option BQuick Check:
keyof Trestricts keys to valid properties [OK]
keyof T to limit keys to object properties [OK]- Using any loses key restriction
- Using unknown does not restrict keys
- Partial<T> affects values, not keys
Ready to prove it?
Pass the test and this pattern moves unknown
