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.

Injectable.provideAs

See original GitHub issue

šŸš€ feature request

Relevant Package

This feature request is for @angular/core, possibly @angular/compiler since this is metadata.

Description

Currently this

@Injectable({ providedIn: AppModule })
export class Service { }

is is a different way to express this

@NgModule({
  providers: [Service]
})
export class AppModule { }

which is in return a short way of saying this.

@NgModule({
  providers: [{ provide: Service, useClass: Service }],
})
export class AppModule { }

It would be nice if it was possible to also be able to express this

@NgModule({
  providers: [{ provide: Token, useClass: Service }],
})
export class AppModule { }

Describe the solution you’d like

@Injectable({ providedIn: AppModule, providedAs: Token })
export class Service { }

This would greatly reduce the ā€œwrite it here and then remember to add it over thereā€ issues, especially since dependency injection by nature isn’t very friendly with static type checking, so these errors can only be discovered at runtime.

Here’s an example with real-life names, to get the better feeling of how this makes many injection patterns easier to read.

Current way

@Injectable()
export class PortalService { }

@NgModule({
  providers: [
    {
      provide: DEFAULT_PORTAL,
      useClass: PortalService,
    },
  ],
})
export class AppModule { }

Proposed way

@Injectable({ providedIn: 'root', providedAs: DEFAULT_PORTAL })
export class PortalService { }

@NgModule({ })
export class AppModule { }

Issue Analytics

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

github_iconTop GitHub Comments

3reactions
JoostKcommented, Dec 6, 2020

I really like how this would offer a more concise way of provider registration, unfortunately however doing the registration in this way is problematic when considering tree-shaking abilities. The providedIn syntax was introduced in Angular 6 to allow tree-shaking of services that would not be referenced from anywhere in the application, allowing a tree-shaker to consider the service implementation as unused and elide it from the build output. This is not true for NgModule.providers, as the application retains strong references into all imported NgModules.

Adding something like providedAs would allow users to only reference the token, without ever referencing the service implementation itself. As such, a tree-shaker would consider the service implementation as unused and elide it from the build output. This would have removed the implicit providedAs registration and prevent users from injecting the service implementation.

In essence this is similar to multi-providers using providedIn (#27477) and using useExisting with providedIn (#33400), both of which are not feasible due to tree-shaking concerns.

1reaction
JoostKcommented, Dec 6, 2020

I’ve read the issues you’ve linked, and would like to check if I am understanding this correctly: the information @Injectable({ providedIn: 'root' }) is resolved at runtime when the service is injected from a constructor? It’s never actually provided before being injected the first time? Then Angular notices the metadata and knows where to provide it (usually 'root'), and then reads it from there?

Yes, that is indeed exactly how it works! This is where the provider metadata is detected:

https://github.com/angular/angular/blob/7954c8dfa3c85d12780949c75f1448c8d783a8cf/packages/core/src/di/r3_injector.ts#L197-L202

The injector has a scope name which allows for the detection of whether or not the providedIn metadata should be used to register the provider implicitly in the injector, indeed upon the first resolution of said service:

https://github.com/angular/angular/blob/7954c8dfa3c85d12780949c75f1448c8d783a8cf/packages/core/src/di/r3_injector.ts#L420-L429

Either way, this is a duplicate of #33400. I guess the only way to work around the tree-shaking issue is for Angular to inject some special comment which would signal ā€œdo not tree-shake thisā€ to the tree-shaker. I’m guessing there’s no unified standard syntax for this across different tree-shaking implementations, so that’s a no-go too. Bummer.

Yeah, there is not something like that that I’m aware of. It would be quite the opposite of the PURE marker that is typically supported in tree shakers. Besides tree-shaking, another pitfall would be that the source file in which the service is declared needs to be actually included into the compilation; either through an explicit import (which is counter-intuitive if not directly used) or using an include or files compilation configuration that picks up the file.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Injectable - Angular
Decorator that marks a class as available to be provided and injected as a dependency. ... Determines which injectors will provide the injectable....
Read more >
DMPA Contraceptive Injection: Use and Coverage - KFF
This factsheet provides an overview of the types of contraceptive injection, use, awareness, availability, and insurance coverage of theĀ ...
Read more >
injectable | Dart Package - Pub.dev
GetIt provides a way to dispose singleton and lazySingleton instances by passing a dispose callBack to the register function, Injectable works in the...
Read more >
FDA Approves First Injectable Treatment for HIV Pre-Exposure ...
Today, the FDA approved Apretude (cabotegravir extended-release injectable suspension) for use in at-risk adults and adolescents weighing atĀ ...
Read more >
Injectable Dermal Fillers Guide | ABCS
Learn all about injectable filler treatments below. Price Range Injectable Fillers ... occurring substance in the skin that provides structure and firmness.
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