Angular Service Missing @Injectable

ID

javascript.angular_use_injectable

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

angular, framework, reliability

Description

Reports a class in an Angular file whose constructor takes class-typed dependencies — the canonical shape of an Angular service — but carries none of Angular’s class decorators (@Injectable, @Component, @Pipe, @Directive, @NgModule).

// Bad — meant to be a service, but no @Injectable.
export class UserService {
  constructor(private http: HttpClient) {}
}

// Good
@Injectable({ providedIn: "root" })
export class UserService {
  constructor(private http: HttpClient) {}
}

Rationale

Angular’s dependency-injection container can only wire instances of classes that opt into the system via a class-level decorator. A bare class with class-typed constructor dependencies looks like a service but isn’t one — every consumer has to provide the dependencies manually, and the single-instance semantics that DI guarantees are gone.

Adding @Injectable (or the matching decorator for components, pipes, directives, and modules) makes the class participate in DI and lets Angular emit the runtime metadata needed to resolve the dependencies.

Remediation

Add the appropriate decorator. For a service, @Injectable({ providedIn: "root" }) registers it as a tree-shakeable singleton:

@Injectable({ providedIn: "root" })
export class UserService {
  constructor(private http: HttpClient) {}
}

If the class genuinely is a plain helper that should not participate in DI, change the constructor signature to remove the class-typed parameters and the rule will stay silent.

Notes

The rule fires only on TypeScript files that import from @angular/* (the file-level Angular heuristic). Within those files, a class is reported when:

  • it has a constructor method,

  • the constructor has at least one parameter typed as a {@code TypeReference} (a user-defined class), and

  • the class has no Angular class decorator.

Predefined-primitive parameters (: string, : number, …​) don’t count toward the dependency check — they are configuration, not DI.