Feature request: top-down dependency injection
See original GitHub issueThe @Service decorator is only called if the implementation of the service is explicitly called. If this typename is known to the constructor, it kind of defeats the point of DI as the controller now has a dependency at least on the name and path of the dependency.
It would be helpful to have a top-down DI initialization where the token is set at fastify initialization.
example use case:
//IBlogService.ts
import { BlogPost } from './models/BlogPost';
export interface IBlogService
{
async getBlogPosts(): Promise<Array<BlogPost>>;
}
//SqliteBlogService.ts
import { IBlogService } from './services/IBlogService';
import { BlogPost } from '../models/BlogPost';
export class SqliteBlogService implements IBlogService {
async getBlogPosts(): Promise<Array<BlogPost>>{ /* ... */ };
}
//BlogController.ts
//SqliteBlogService @Service is never called because it's never explicitly imported anywhere
import { IBlogService } from '../services/IBlogService';
@Controller({
route: '/api/blogposts'
})
export class BlogController {
constructor(private blogService: IBlogService) { }
@GET()
public async getBlogPosts(req, res): Promise<Array<BlogPosts>> {
return this.blogService.getBlogPosts();
}
}
Top down injection could be something like:
//app.ts
import { injectables } from 'fastify-decorators';
import { IBlogService } from './services/IBlogService';
//injection goes before constructor discovery
if(environment === 'development') {
injectables.injectSingleton<IBlogService>(new SqliteBlogService());
} else if(environment === 'production') {
injectables.injectSingleton<IBlogService>(new MySQLBlogService());
}
fastify.register(bootstrap, {
/* ... */
})
this would allow services to be defined as interfaces so that you’re not dependent on any particular implementation within the controllers, which is the point of DI
The workaround is to simply import whatever implementations you want in app.ts so that the @Service decorator is called before the @Inject decorators in the controller, but this is obviously code smell
Issue Analytics
- State:
- Created a year ago
- Comments:6 (4 by maintainers)

Top Related StackOverflow Question
Published as v3.15.0
It’s purely depends on you bootstrap style, in case when you use autoload option and import service directly within you index.ts, then import of service is executed before controllers and their dependencies are loaded, but it can not work in case when you specify controllers to be loaded and it can depends on imports order. Long story short: it depends who was required/imported first, but yeah, can agree, this is code smell