2
votes

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

2
"...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.T.J. Crowder

2 Answers

4
votes

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

0
votes

Creating a new instance of FooImpl generates an error (when passing no args to the constructor, because the constructor is inherited) thereby forcing the usage of the constructor with args:

const f = new FooImpl();
Expected 1 arguments, but got 0.