dudewad dudewad - 1 month ago 16
TypeScript Question

Can't extend superclass when using @Inject with Angular 2

Contrary to everything I've read, I seem unable to extend a class where the base class requires an injected OpaqueToken reference.

Example:

@Component({})
export class StructureBase_Cmp {
constructor(private constants:App_Const){
}
}


In this example,
App_Const
comes from an OpaqueToken that is provided in the module as such:

providers: [
{provide: App_Const, useValue: Constants}
],


I am aware that for whatever reason you need to call @Inject, thus changing the first example to this:

@Component({})
export class StructureBase_Cmp {
constructor(@Inject(App_Const) private constants){
}
}


This works fine. What does not work fine is trying to extend that class because it complains that "private constants" is of a different type in the derived class:

@Component({})
export class Hero_Cmp extends StructureBase_Cmp{
constructor(@Inject(App_Const) protected constants) {
super(constants);
}
}


However, I can't change the super class to this:

@Component({})
export class StructureBase_Cmp {
constructor(private constants:App_Const){
}
}


because.... what, App_Const is an OpaqueToken and not a defined Type? Despite the docs, I'm extremely confused because this feels like some flavor of this should work right out of the box.

tldr:
I want to extend a class that requires an injected item that is derived from an OpaqueToken, however in order to do so I need to use @Inject on the derived class, which for whatever reason breaks the parent class.

Any help is appreciated. Thanks.

Answer

I would say that the issue is not related to angular nor IoC. It is just an typescript compiler check (observe it here):

export class StructureBase_Cmp {
    constructor(private constants){
    }
}

export class Hero_Cmp extends StructureBase_Cmp{
    constructor(protected constants) {
        super(constants);
    }
}

will produce error:

Class 'Hero_Cmp' incorrectly extends base class 'StructureBase_Cmp'.
Property 'constants' is private in type 'StructureBase_Cmp' but not in type 'Hero_Cmp'. class Hero_Cmp

because parent has a property private, while child protected. That does not make sense.

just make it protected as well

export class StructureBase_Cmp {
    constructor(protected constants){ // also protected
    }
}

export class Hero_Cmp extends StructureBase_Cmp{
    constructor(protected constants) {
        super(constants);
    }
}
Comments