Reputation: 475
I am working with Nest.js + TypeORM and hit a snag when trying to add inheritance to service classes.
I want to have a User service class that extends off of a Base service class, inheriting all the methods the it has.
This is what I've done:
export class BaseService<T> {
private repo;
constructor(repo: Repository<T>){
this.repo = repo;
}
async findAll(opts?): Promise<T[]> {
return this.repo.find(opts);
}
......
}
Then on my User service:
export class UserService extends BaseService<User> {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
private readonly mailerService: MailerService,
) {
super(userRepository);
}
}
This works fine where I just need a single repository in the Service class but once I need more such as productRepository, as you can see it would fail due to constructor being hardcoded to accept a single repository.
I can't seem to figure out what would be the most elegant way of achieving something like this.
Does anyone know?
Upvotes: 0
Views: 2414
Reputation: 963
It is an old thread, anyways I meat this same problem and this answer may help someone else...
You can have an abstract class with common functions and boilerplate that you wich to be available in all your repositories to maintain patterns and so on...
export abstract class BaseService<T extends ObjectLiteral> {
protected repo: Repository<T>;
async findAll(opts?): Promise<T[]> {
return this.repo.find(opts);
}
......
}
Observe that constructor is omitted here and as an abstract class you should never have an instance of it, it is meant to be just an extension with common boilerplates and features that you don't want to write every single time you need a new service with the same features like a CRUD service or so...
Then you will use it like this:
export class UserService extends BaseService<User> {
constructor(
@InjectRepository(User) protected readonly repo: Repository<User>,
private readonly mailerService: MailerService,
) {
super();
}
...... extended stuff
}
I'm not sure if you need to inject repo with the same name and visibility but as it worked for me I didn't dive any further to get to know...
The bad side of this approach to me is that even if you don't have anything else to inject via constructor in your service you need to declare constructor and inject the base repository... it is a boilerplate that could be avoided too but I couldn't achieve this right now...
Upvotes: 1