Injection of Generic Services in Angular

An additional instance won't be created for generics. As it is stated here, reflect-metadata (which is used by Angular 2 decorators to support TypeScript type annotations) can't obtain this kind of information:

TypeScript only emits type metadata for types available at run time, and does not emit type aliases, interfaces, or generics (as they do not have a JavaScript representation).

The amount of MyService instances depends on whether MyService was defined as component's provider or it was inherited from parent injector.

In the code above, ComponentA and ComponentA1 can inherit MyService provider from parent injector, ComponentB can get a new instance with providers: [MyService].


This is a simple solution:

// service and models
export class User {
  firstName: string
}

export class Admin {
  lastName: string
}

@Injectable()
export class GenericService<T>{
  item: number = Math.random();
  GetAll(): Array<T> {
    let output = [];
    console.log(this.item); // each instance has own value
    return output;
  }
}

Then set your service in module through useFactory:

providers: [
  { provide: 'UserService', useFactory: () => (new GenericService<User>()) },
  { provide: 'AdminService', useFactory: () => (new GenericService<Admin>()) },
],

and inject your service with @Inject decorator:

constructor(
  @Inject('UserService') private userService: GenericService<User>,
  @Inject('AdminService') private adminService: GenericService<Admin>
) { }

Keep in mind it is better to use InjectionToken ( OpaqueToken is deprecated) for your provider token.I have used string just for simplicity.

Tags:

Angular