Is @Inject really only needed for the cases when not transpiling with TS or emitDecoratorMetadata:false

178 Views Asked by At

I'm reading this article on @Injectable and @Inject and it has the following:

Problem solved. In fact, this is exactly what @Inject is for when not transpiling with TypeScript. If we take a look at the transpiled code now, we see that all the needed metadata is generated (yeap simplified).

...

We can basically put any decorator on our code, as long as it’s either attached to the class declaration, or to the constructor parameter. In other words, we could remove @Inject again and use something else that we put on the class, because that will cause TypeScript to emit metadata for the constructor parameters too... Luckily, Angular comes with yet another decorator we can use. @Injectable is normally used for Dart metadata generation. It doesn’t have any special meaning in TypeScript-land, however, it turns out to be a perfect fit for our use case.

So, is my understanding correct, that:

  1. If a class is used as injectable for other classes but is not dependent on any other class, it doesn't need neither @Injectable nor @Inject in the constructor
  2. If a class is dependent on any other class and doesn't have any decorator used on it, it requires @Injectable() decorator
  3. If TS is used with emitDecoratorMetadata:true, @Inject decorator is of no use
  4. If TS is not used, or used with emitDecoratorMetadata:false, @Inject is the only mechanism to specify the dependency
1

There are 1 best solutions below

3
On BEST ANSWER
  1. Yes, AFAIK ("dependent on any other class" see below, there are other kind of dependencies than classes)

  2. Yes, but using @Injectable() is preferred AFAIK.

  3. @Inject() is required when the type of the parameter doesn't match the type the providered is registered with.

providers: [
  MyService,
  {provide 'myservice', useClass: MyService},
  {provide myserviceOpaqueToken, useClass: MyService},
]
constructor(private myService:MyService) {} // no @Inject() required
constructor(@Inject('myservice') private myService:MyService) {} //  @Inject() used to lookup the provider by string name
constructor(@Inject(myserviceOpaqueToken) private myService:MyService) {} //  @Inject() used to lookup the provider by OpaqueToken

This also reveals some misconceptions in your other statements. Classes can depend on other parameters than on other classes

providers: [
  {provide 'myconfigvalue', useValue: '42'},
]

constructor(@Inject('myconfigvalue') private myConfigValue:string) {}   
  1. There is also the static get parameters() { ... } getter to specify dependencies. I guess this is still valid for using Angular2 with ES5/6 (never used it myself)

https://medium.com/@blacksonic86/angular-2-dependency-injection-in-es6-f5551a3d6bf#.kgxjvcinv

@Component({
  selector: 'app',
  template: `
    <ul>
      <li *ngFor="#city of getCities()">{{ city }}</li>
    </ul>
  `
})
class AppComponent {
  static get parameters() {
    return [[CityService]];
  }

  constructor(cityService) {
    this._cityService = cityService;
  }

  getCities() {
    return this._cityService.getCities();
  }
}