Binding a class to an interface

前端 未结 2 2057
伪装坚强ぢ
伪装坚强ぢ 2020-12-24 01:55

Using typescript, I can easily bind classes to themselves:

bootstrap(MyAppComponent, [MyClass]);

However, I would like to bind my class to

相关标签:
2条回答
  • 2020-12-24 02:35

    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).
    
    0 讨论(0)
  • 2020-12-24 02:39

    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 typescript
    class 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.

    0 讨论(0)
提交回复
热议问题