I am building a REST API and want to create a generic base repository to handle CRUD operations. How do I use TypeScript Generics to ensure that my 'find' and 'update' methods return the correct entity types while maintaining a clean, reusable class structure across different modules?
3 answers
The key is defining a base class like BaseRepository<T>. You can then use T as the return type for your methods. For the update method, use Partial<T> to allow passing only the fields that need changing. This setup allows you to extend the base class for specific entities like UserRepository extends BaseRepository<User>. This gives you all the standard CRUD logic for free while still allowing you to add entity-specific queries without repeating the basic boilerplate code.
How do you handle database-specific errors within a generic repository without tightly coupling your business logic to a specific ORM like TypeORM or Prisma?
Generics are perfect for this. I also suggest using an interface to define the contract for the repository to make unit testing with mocks much easier.
Totally agree. Using interfaces with generics is the best way to ensure your code remains testable and modular as the project grows in size.
That is where the Data Mapper pattern comes in, Steven. You can define an interface for your repository and have the implementation handle the ORM-specific errors, then map them to custom domain errors. This keeps your generic logic clean and decoupled from the database.