angulartypescriptdependency-injectiontree-shaking

Treeshakeable providedIn-Syntax while separating service interface from implementation(s)


In my angular project i want to split my services into interfaces (abstract classes) and implementations (implementing those interfaces). E.g. from

import { Injectable } from "@angular/core";
import { ImpyService } from "./implementation/impy.service";

@Injectable({
  providedIn: 'root',
})
export class AggyService {

  doSomething() {
    // ...
  }

}

to

// "Interface"..

@Injectable({
  providedIn: 'root'
})
export abstract class AggyService {

  abstract doSomething();

}

// & "Implementation..

@Injectable()
export class ImpyService implements AggyService{

  doSomething() {
    // do something
  };

}

Now, since AggyService is abstract it can only be used the the injection key and i have to specify the implementation as the injection value/provider and add it to the providers-property in an NgModule, Component, or Inject() it 'directly'.

E.g. when wanting it to be globally available in my app.module.ts

@NgModule({
  //  ...,
  providers: [
    { provide: AggyService, useClass: ImpyService }
  ]
})
export class AppModule { }

But - as far as i know - this prevents tree-shaking as the service now is imported in app.module.ts.

I found, that i can specify the provider in the @Injectable()-decorator like so

@Injectable({
  providedIn: 'root',
  useClass: ImpyService
})
export abstract class AggyService {

  abstract doSomething();

}

This works (for now), but also, seems to be undocumented (e.g. see https://angular.io/api/core/Injectable).

I really don't want to stick to undocumented stuff, but i don't know how to do this another way.

How to go about this?


Solution

  • As i just wanted to create an issue for this, i found, that this already exists and seems to be added to the documentation somewhere in the future...

    (see https://github.com/angular/angular/issues/34107)