question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Contradicting and incorrect Injectable docs

See original GitHub issue

📚 Docs or angular.io bug report

Description

I wanted to know how Injectable worked and whether or not we are actually required to use it (not that I want to omit it, just as a matter of understanding how things work).

At first, I thought Injectable was always required for any service that’s used (either by adding it to the providers or using providedIn, which requires Injectable anyway) in Angular.

However, we noticed that Injectable is only required to be used as a decorator on a service that has dependencies which are being injected into its constructor.

This was easily verified using a Stackblitz: https://stackblitz.com/edit/angular-pgkrb5

  • If you would omit the @Injectable from FooService, it’ll show an error: Can't resolve all parameters for FooService: (?)..
  • If you would inject BarService (which has no @Injectable) into the AppComponent, everything works fine as well.

However, doing some more testing it turns out we can replace the Injectable decorator with any other decorator, even the HostBinding works: https://stackblitz.com/edit/angular-qkngb5

Doing some googling on this quickly showed me I wasn’t the first one noticing this, so this is not really something new I guess.

However, in order to fully understand how it worked, I needed to fiddle with Stackblitz, the docs didn’t really give me a proper answer. I found some things I wanted to update to be more accurate if anyone else ever would have the same question as I had.

As I don’t think the above findings are things that necessarily need to end up in the docs, I thought I would be better of creating an issue first to discuss this further before creating a PR to update the docs.

A few remarks on snippets from the docs

https://angular.io/api/core/Injectable

Injector throws an error if it tries to instantiate a class that is not decorated with @Injectable, as shown in the following example.

I think this isn’t entirely correct, it’s only the case when that service has dependencies which are being injected in its constructor.

https://angular.io/guide/dependency-injection#services-that-need-other-services

Notice that the Logger service also has the @Injectable() decorator, even though it might not need its own dependencies. In fact, the @Injectable() decorator is required for all services.

When Angular creates a class whose constructor has parameters, it looks for type and injection metadata about those parameters so that it can inject the correct service. If Angular can’t find that parameter information, it throws an error. Angular can only find the parameter information if the class has a decorator of some kind. The @Injectable() decorator is the standard decorator for service classes.

Both snippets above might be a bit contradicting, the first one mentions it’s required for all services. While the second snippet is mentioning the fact that the class’ constructor needs to have parameters.

What I’d propose to change:

https://angular.io/api/core/Injectable:

Injector throws an error if it tries to instantiate a class that is not decorated with @Injectable and is making use of Dependency Injection (add link to https://angular.io/guide/dependency-injection or https://angular.io/guide/dependency-injection#services-that-need-other-services here), as shown in the following example.

Maybe we can also include an example that shows it doesn’t throw in case we omit Injectable and have no Dependency Injection.

https://angular.io/guide/dependency-injection#services-that-need-other-services

Notice that the Logger service also has the @Injectable() decorator, even though it might not need its own dependencies. Even though it’s not required to add Injectable when you’re not making use of Dependency Injection, we do encourage adding it as this will make it easier to add dependencies later on.

When Angular creates a class whose constructor has parameters, it looks for type and injection metadata about those parameters so that it can inject the correct service. If Angular can’t find that parameter information, it throws an error. Angular can only find the parameter information if the class has a decorator of some kind. The @Injectable() decorator is the standard decorator for service classes.

Even tho this still isn’t 100% correct (as Injectable isn’t required, any decorator should do), I think this could be an improvement.

I’m also not aware if Ivy would change anything with regards to this, if this is the case these changes might be obsolete.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ogurcommented, Apr 11, 2020

With Angular 9 and Ivy any decorator not longer works (it needs to be Injectable), but the rest of the post is true and should be fixed.

1reaction
trotylcommented, May 17, 2019
Read more comments on GitHub >

github_iconTop Results From Across the Web

Advanced Scenarios — Simple Injector 5 documentation
Property injection; Covariance and Contravariance; Registering plugins dynamically; Accessing a dependency's metadata. Generics¶ .
Read more >
Hierarchical injectors - Angular
With hierarchical dependency injection, you can isolate sections of the application and give them their own private dependencies not shared with the rest...
Read more >
4.3 Dependencies - Spring
DI exists in two major variants, namely Constructor Injection and Setter ... throws an exception as a result of a missing or invalid...
Read more >
microsoft/tsyringe: Lightweight dependency injection container ...
Lightweight dependency injection container for JavaScript/TypeScript ... See the linked source code for up to date documentation on available options.
Read more >
When do we need to use @Injectable on our services in ...
I don't know who wrote the documentation for @Injectable or when it was written, but it is completely misleading:.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found