TypeScript
/Advanced
Repository Pattern
Definition
An architecture pattern that mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
Explain Like I'm New
Your business logic (e.g., 'Calculate User Taxes') shouldn't care if the user data is saved in a PostgreSQL database, a MongoDB database, or a simple JSON file. The Repository is a shield between your logic and the database. It provides clean methods like `UserRepository.findById(id)`.
Real World Example
Heavily used in Node.js backends (like NestJS or TypeORM). You inject a `UserRepository` into your service, completely decoupling your code from the underlying SQL queries.
Common Use Cases
- •Backend TypeScript architecture
- •Decoupling business logic from databases
- •Making code easily testable/mockable
Interactive Example
// 1. The Generic Interface Contract interface IRepository<T> { findById(id: string): Promise<T>; save(item: T): Promise<void>; } interface User { id: string; name: string; } // 2. The Concrete Implementation (e.g., using MongoDB) class MongoUserRepository implements IRepository<User> { async findById(id: string) { console.log(`Executing Mongo query for ${id}...`); return { id, name: "Alice" }; } async save(user: User) { console.log(`Saving ${user.name} to MongoDB...`); } } // 3. Business Logic (Completely blind to MongoDB!) class UserService { // It only asks for the Interface contract constructor(private repo: IRepository<User>) {} async upgradeUser(id: string) { const user = await this.repo.findById(id); // business logic here... await this.repo.save(user); } }
Interview Questions
basic
- What is the main goal of the Repository Pattern?
intermediate
- How do Generics power a Base Repository?
advanced
- How does this pattern make unit testing easier?