i wonder if there is a proper way to inject interfaces in Angular2? (cf. below)
I think this is related with the missing @Injectable() decorator on the interface, bu
The reason you can't use interfaces is because an interface is a TypeScript design-time artifact. JavaScript doesn't have interfaces. The TypeScript interface disappears from the generated JavaScript. There is no interface type information left for Angular to find at runtime.
Solution 1:
The easiest solution is just to define an abstract class which implements the interface. Often, you need a abstract class anyway.
Interface:
import {Role} from "../../model/role";
export interface ProcessEngine {
login(username: string, password: string):string;
getRoles(): Role[];
}
Abstract Class:
import {ProcessEngine} from "./process-engine.interface";
export abstract class ProcessEngineService implements ProcessEngine {
abstract login(username: string, password: string): string;
abstract getRoles(): Role[];
}
Concrete Class:
import { Injectable } from '@angular/core';
import {ProcessEngineService} from "./process-engine.service";
@Injectable()
export class WebRatioEngineService extends ProcessEngineService {
login(username: string, password: string) : string {...}
getRoles(): Role[] {...}
}
Now you can define your provider like usual:
@NgModule({
...
providers: [
...,
{provide: ProcessEngineService, useClass: WebRatioEngineService}
]
})
Solution 2:
The official documentation of Angular suggest to use the InjectionToken, similar to OpaqueToken. Here is the Example:
Your interface and class:
export interface AppConfig {
apiEndpoint: string;
title: string;
}
export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};
Define your Token:
import { InjectionToken } from '@angular/core';
export let APP_CONFIG = new InjectionToken('app.config');
Register the dependency provider using the InjectionToken object, e.g in your app.module.ts:
providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]
Than you can inject the configuration object into any constructor that needs it, with the help of an @Inject decorator:
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}