Abstract Constructor on Abstract Class in TypeScript

12,461

Actually in Typescript if you don't override the constructor, the constructor is inherited form the base class.

So in your case this would be invalid:

new FooImpl(); // error 

You would be forced to pass the parameters required by the base class:

new FooImpl("") //ok

There is no way to force the derived type to override the constructor, but since the base constructor is inherited it seems to be good enough.

Playground link

Share:
12,461

Related videos on Youtube

Neil Stevens
Author by

Neil Stevens

Senior Software Engineer working at APD Communications

Updated on June 04, 2022

Comments

  • Neil Stevens
    Neil Stevens over 1 year

    How can I create an abstract constructor for an abstract class?

    For example, if I have this abstract class:

    export abstract class Foo<T> extends Bar<T> {
      constructor(someParam: any) {
        super();
        this.someObj = someParam;
      }
    }
    

    Then it is consumed by this class:

    export class FooImpl extends Foo<SomeType> {
    }
    

    If I don't override the constructor then the default parameterless constructor will be used on the FooImpl class which will lead to an improper state within the class.

    How can I define an abstract constructor or force consumers of the abstract class to override the constructor when Foo<T> is consumed?

    EDIT

    The exact code I have is below and would appear that this is somehow related to vscode

    export abstract class FireStoreDataSource<T> extends DataSource<T> {
      constructor(store: () => Observable<T[]>) {
        super();
      }
    }
    

    Then I am extending this class as follows

    export class AssessmentCenterDataSource extends FireStoreDataSource<AssessmentCenter> {
    }
    

    Then creating an instance in an angular component ngOnInit

    ngOnInit() {
      this.dataSource = new AssessmentCenterDataSource(() => this.service.getData());
    }
    

    Here in vscode I am getting the compiler error [ts] Expected 0 arguments, but got 1., however when I run ng build it does build correctly

    If I do not pass anything to the constructor then the compiler error goes away and I get an error when I run ng build which is error TS2554: Expected 1 arguments, but got 0.

    So it looks like this might be an issue with vscode or one of the addons I have installed rather than typescript

    I am using vscode insiders 1.26.0 and typescript insiders 3.0.1 along with Angular 6

    • T.J. Crowder
      T.J. Crowder over 5 years
      "...then the default parameterless constructor will be used on the FooImpl class which will lead to an improper state within the class." Leaving aside that the default won't be parameterless, improper in what way? The code in the super constructor must be executed, it's a requirement of class syntax. If you added a constructor to the subclass and didn't call super, it would be an error.
  • Neil Stevens
    Neil Stevens over 5 years
    This is not the case in my example I do not get any compiler error
  • Titian Cernicova-Dragomir
    Titian Cernicova-Dragomir over 5 years
    @NeilStevens then something else might be at work, this is how it's supposed to behave. Added a playground link with your exact code and we get an error. Maybe your real code differs in some way ? Are the parameters optional ?
  • Neil Stevens
    Neil Stevens over 5 years
    To elaborate, in the above (in vscode) I get a compiler error for the second one if I pass an argument
  • Titian Cernicova-Dragomir
    Titian Cernicova-Dragomir over 5 years
    @NeilStevens this seems strange. are you sure the class you are instantiating the correct class ? Are your imports ok ? What compiler settings are you using (although I can't really think of one that would impact this behavior)
  • Titian Cernicova-Dragomir
    Titian Cernicova-Dragomir over 5 years
    @NeilStevens I am 100% sure of the answer provided. At least in recent versions of typescript this is the behavior (I suspect it has always been but would need to check)
  • Ric
    Ric over 5 years
    Something is not quite right then, this is default behavior.
  • Neil Stevens
    Neil Stevens over 5 years
    Please see updated question which include the real code (although somewhat cut back to remove irrelevant code) but you will see that I am doing exactly as you state above so I will raise this with the vscode team
  • Ric
    Ric over 5 years
    I have just copied your code and can say that I get an error if no function is passed to new AssessmentCenterDataSource(....)
  • Neil Stevens
    Neil Stevens over 5 years
    Strange, after restarting the IDE all is correct, must make a mental note to restart the IDE before jumping on SO and looking like a fool
  • Titian Cernicova-Dragomir
    Titian Cernicova-Dragomir over 5 years
    @NeilStevens I'm no longer at my desk but I'll try with the dev version when I can. Have you tried with 2.9? It might be an editor issue..
  • Ric
    Ric over 5 years
    when nothing makes sense anymore, computer rebooting is in order :)