What is in Angular 2 Opaque Token and What’s the Point?

update Angular4

In Angular4 OpaqueToken is deprecated and will be replaced by InjectionToken.
InjectionToken allows to pass a generic type parameter.

export let APP_CONFIG = new InjectionToken<MyConfig>("app.config");

See also

original

What? What’s an Angular2 token to begin with?

What’s an Opaque Token? What is it used for?

A token is a key for providers of Angulars dependency injection.
Providers are registered with a key and components, directives, and service classes instantiated by DI get dependencies injected which are looked up by provider keys.

DI supports types, strings, OpaqueToken and objects as keys.

export let APP_CONFIG = new OpaqueToken("app.config");

export let APP_CONFIG_2 = {};

providers: [
  MyService, // type is key and value
  {provide: MyService, useClass: MyFancyServiceImpl}, // type is key, `MyFancyServiceImpl` is the value (or rather the information how to create the value
  {provide: 'myservice', useClass: MyService}, // key is a string
  {provide: APP_CONFIG, useValue: {a: 'a', b: 'b'}} // key is an `OpaqueToken`
  {provide: APP_CONFIG_2, useValue: {a: 'a', b: 'b'}} // key is an object

]
// one of these decorators needs to be added to make DI work
@Injectable()
@Component()
@Directive()
@Pipe()
class MyComponent {
  // DI looks up a provider registered with the key `MyService` 
  constructor(private myService: MyService) {} 

  // Same as before but explicit
  constructor(@Inject(MyService) private myService: MyService) {} 

  // DI looks up a provider registered with the key 'myService'
  constructor(@Inject('myservice') private myService: MyService) {} 

  // DI looks up a provider registered with the `OpaqueKey` `APP_CONFIG`
  constructor(@Inject(APP_CONFIG) private myConfig: any) {} 

  // DI looks up a provider registered with the object `APP_CONFIG_2`
  constructor(@Inject(APP_CONFIG_2) private myConfig: any) {} 

The object key (APP_CONFIG_2) and the OpaqueToken (APP_CONFIG) need to be the exact same instance. A different instance with the same content won’t work. This makes it easy to look up where the key is declared and whether the provider and the injection target use the same key.

For a string it can be a different instance, this brings the risk, that the same string value is used in different modules and might cause conflicts or the wrong provider being injected.

Leave a Comment