Question presented to candidate:
"Our components never call new on the services they use, yet they always get a working instance. Walk me through what Angular's dependency injection is actually doing behind the scenes."
What a strong answer should cover:
- Dependency injection means a class declares what it needs and something else builds and hands it over; in Angular that something is an injector.
- A provider is the recipe (token to "how to make it");
@Injectable({ providedIn: 'root' }),providers: [...]arrays andprovideX()functions all register providers. - Injectors form a tree: element injectors (from component and directive
providers) are searched first, then environment injectors (root, route, platform), ending in a null injector that throws. - Instances are created lazily and cached per injector, so a root service is a singleton and is never built if nobody asks for it.
- Dependencies are requested with
inject()(or constructor parameters, which the compiler turns into the same calls). - A missing provider fails with NG0201 ("No provider found for ..."), including the dependency path.
Clarifying questions expected:
- "Do you want the mental model, or the compiled output too?"
- "Standalone app or NgModule-based? The injector tree is the same, but where providers are registered differs."
Code / implementation expected: Optional — a service that depends on another service, injected into a component, plus what happens when a provider is missing.