@Injectable + inject() — One-Liner DI
Services & Dependency Injection
A service is a plain class with @Injectable. Components reach for it via the inject() function — no constructor wiring needed.
What you'll learn
- Decorate a service with @Injectable
- Inject it with the inject() function
- Compare inject() to constructor injection
Angular’s dependency injection is one of its oldest superpowers. A service is just a class — the framework constructs it on demand and hands the same instance to every consumer.
Define a service
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
export interface User { id: string; name: string }
@Injectable({ providedIn: 'root' })
export class UsersService {
private http = inject(HttpClient);
list() {
return this.http.get<User[]>('/api/users');
}
} providedIn: 'root' makes it an application-wide singleton — and tree-shakable. If nothing injects it, the bundler can drop it entirely.
Inject from a component
import { Component, inject } from '@angular/core';
import { UsersService } from './users.service';
@Component({
selector: 'app-users',
standalone: true,
template: `<p>{{ users().length }} users</p>`,
})
export class UsersComponent {
private users$ = inject(UsersService).list();
users = toSignal(this.users$, { initialValue: [] });
} Constructor vs inject()
The old constructor form still works:
constructor(private users: UsersService) {} But inject() is preferred because it works anywhere inside an injection context — field initializers, factory functions, route guards, resolvers, interceptors. No constructor required.