Binding a class to an interface Binding a class to an interface angular angular

Binding a class to an interface


To make it short the problem is that Interfaces disappear when typescript is compiled. So you'd have to use @Inject with a string.

Or there's another option, if you check the last article of Victor Savkin you can find this in the comments :

Some background. In TypeScript, interfaces are structural and are not retained at runtime. So you have to use ILoginService as follows:

constructor(@Inject("ILoginService") s:ILoginService).

You don't have to use a string - any object can be passed in there. We actually provide an object called OpaqueToken that can be used for this purpose.

interface ILoginService { login(credentials);}const ILoginService = new OpaqueToken("LoginService");

can be used like this:

constructor(@Inject(ILoginService) s:ILoginService).


I dont know if it is possible with interface as interface will not be available at runtime (javascript does not know about interface).But it can be done using abstract classes.

//abstract-parent-service.ts

export class DatabaseService{    getService: ()=>string;}

//hibernate.service.ts

import {DatabaseService} from "./abstract-parent-service";export class HibernateService implements DatabaseService{  constructor() { }  getService() {    return "i am hibernate";  }}

//jdbc.service.ts

import {DatabaseService} from "./abstract-parent-service";export class JDBCService implements DatabaseService{  constructor() { }  getService() {    return "i am Jdbc";  }}

//cmp-a.component.ts

import {DatabaseService} from "./abstract-parent-service";import {HibernateService} from "./hibernate.service";@Component({    selector: 'cmp-a',    template: `<h1>Hello Hibernate</h1>`,    providers: [{provide: DatabaseService, useClass: HibernateService}]})export class CmpAComponent {    constructor (private databaseService: DatabaseService) {        console.log("Database implementation in CompA :"+this.databaseService.getService());    }}

//cmp-b.component.ts

import {DatabaseService} from "./abstract-parent-service";import {HibernateService} from "./hibernate.service";@Component({    selector: 'cmp-b',    template: `<h1>Hello Jdbc</h1>`,    providers: [{provide: DatabaseService, useClass: JDBCService}]})export class CmpAComponent {    constructor (private databaseService: DatabaseService) {        console.log("Database implementation in CompA :"+this.databaseService.getService());    }}

But the problem with this implementation is HibernateService and JDBCService are not able to extend any other class now because they have already got married with DatabaseService.

class A{    constructor(){        console.log("in A");    }}class B extends A{    constructor(){        super();        console.log("in B");    }}class C extends A{    constructor(){        super();        console.log("in C");    }}let c = new C();//This thing is not possible in typescriptclass D extends B, C{//error:  Classes can only extend a single class    constructor(){        super();// which constructor B or C        console.log("in D");    }}

If you are using this pattern for DI, make it sure that your child class services are not going to extend any other functionality in future.