The generic factory pattern helps create objects without specifying exact classes. It makes code flexible and reusable.
Generic factory pattern in Typescript
interface Factory<T> {
create(): T;
}
class ConcreteFactory<T> implements Factory<T> {
constructor(private creator: () => T) {}
create(): T {
return this.creator();
}
}The Factory interface defines a method to create objects of type T.
The ConcreteFactory class takes a function that creates objects and uses it to produce new instances.
create method that returns an object of type T.interface Factory<T> {
create(): T;
}T.class ConcreteFactory<T> implements Factory<T> { constructor(private creator: () => T) {} create(): T { return this.creator(); } }
Dog objects and use it to make a dog that can speak.class Dog { speak() { return 'Woof!'; } } const dogFactory = new ConcreteFactory(() => new Dog()); const dog = dogFactory.create(); console.log(dog.speak());
This program defines a generic factory pattern to create Cat and Dog objects. Each factory uses a function to create the right animal. Then it calls speak() on each animal.
interface Factory<T> {
create(): T;
}
class ConcreteFactory<T> implements Factory<T> {
constructor(private creator: () => T) {}
create(): T {
return this.creator();
}
}
class Cat {
speak() { return 'Meow!'; }
}
class Dog {
speak() { return 'Woof!'; }
}
const catFactory = new ConcreteFactory(() => new Cat());
const dogFactory = new ConcreteFactory(() => new Dog());
const cat = catFactory.create();
const dog = dogFactory.create();
console.log(cat.speak());
console.log(dog.speak());You can use arrow functions or normal functions as creators.
This pattern helps keep your code clean and easy to extend.
Using generics ensures type safety when creating objects.
The generic factory pattern creates objects without knowing their exact class.
It uses a generic interface and a creator function to make objects.
This pattern makes your code flexible and easy to add new types.
Practice
What is the main purpose of the Generic factory pattern in TypeScript?
Solution
Step 1: Understand the pattern's goal
The generic factory pattern is designed to create objects without needing to know their exact class ahead of time.Step 2: Compare options with the pattern's purpose
To create objects without specifying their exact class. correctly states this purpose. Other options describe unrelated features.Final Answer:
To create objects without specifying their exact class. -> Option BQuick Check:
Generic factory pattern = create objects flexibly [OK]
- Confusing with async handling
- Thinking it enforces variable typing
- Assuming it optimizes runtime speed
Which of the following is the correct syntax to declare a generic factory function in TypeScript?
function create<T>(): T { /* ... */ }Solution
Step 1: Analyze generic function syntax
The function declares a generic typeTand returns an object of typeT.Step 2: Check return statements for correctness
function create<T>(): T { return {} as T; } uses a type assertion{} as Twhich is valid to create a generic placeholder object. function create<T>(): T { return new T(); } tries to usenew T()which is invalid becauseTis a type parameter, not a constructor. function create<T>(): T { return T(); } callsT()like a function which is invalid. function create<T>(): T { return new Object(); } returns a generic object but not typed asT.Final Answer:
function create<T>(): T { return {} as T; } -> Option DQuick Check:
Generic factory syntax = use type assertion [OK]
- Trying to instantiate generic type with new
- Calling generic type as a function
- Returning untyped objects without assertion
What will be the output of this TypeScript code using a generic factory pattern?
interface Animal { speak(): string; }
class Dog implements Animal { speak() { return "Woof"; } }
function createAnimal<T extends Animal>(ctor: new () => T): T {
return new ctor();
}
const dog = createAnimal(Dog);
console.log(dog.speak());Solution
Step 1: Understand the factory function behavior
The functioncreateAnimaltakes a constructorctorand returns a new instance of typeTwhich extendsAnimal.Step 2: Trace the code execution
We passDogclass tocreateAnimal, so it returns a newDoginstance. Callingdog.speak()returns "Woof".Final Answer:
"Woof" -> Option AQuick Check:
Generic factory creates Dog, speak() = "Woof" [OK]
- Assuming generic type can't be instantiated
- Confusing type constraints with runtime errors
- Expecting undefined instead of method return
Identify the error in this generic factory function and select the fix.
function createInstance<T>(): T {
return new T();
}Solution
Step 1: Identify why
TypeScript does not allownew T()causes errornew T()becauseTis a type parameter, not a constructor function.Step 2: Apply correct fix using constructor parameter
Passing a constructor functionctor: new () => Tallows callingnew ctor()to create an instance ofT.Final Answer:
Add a constructor parameter:ctor: new () => Tand returnnew ctor(). -> Option AQuick Check:
Generic factory needs constructor parameter [OK]
- Trying to instantiate generic type directly
- Removing new keyword incorrectly
- Changing return type to any loses type safety
You want to create a generic factory that can produce different shapes with a draw() method. Which approach correctly uses the generic factory pattern to support adding new shapes easily?
interface Shape { draw(): void; }
class Circle implements Shape { draw() { console.log("Circle"); } }
class Square implements Shape { draw() { console.log("Square"); } }
// What is the best factory implementation?Solution
Step 1: Understand the requirement for flexibility
The factory should create any shape implementingShapewithout hardcoding types.Step 2: Evaluate each option
function createShape(ctor: new () => T): T { return new ctor(); } uses a generic constructor parameter allowing easy addition of new shapes. function createShape(): Shape { return new Circle(); } always returns Circle, no flexibility. function createShape(type: string): Shape { if(type === 'circle') return new Circle(); else return new Square(); } uses string checks, less type-safe and harder to extend. function createShape<T>(): T { return {} as T; } returns an empty object cast toT, which is unsafe.Final Answer:
function createShape<T extends Shape>(ctor: new () => T): T { return new ctor(); } -> Option CQuick Check:
Generic factory with constructor param = flexible shape creation [OK]
- Hardcoding return types limits extensibility
- Using string type checks reduces type safety
- Casting empty objects loses real behavior
Ready to prove it?
Pass the test and this pattern moves unknown
