abstract class Route {
abstract readonly name?: string;
protected abstract pattern: string;
public constructor() {
// Do something with `this.name` and `this.pattern`.
console.log(this.pattern); // Typecheck error
}
abstract handle(): void;
}
This throws an error because this.pattern
is not to be accessed in the constructor. Why can't I access it?
(Converting my comments to an answer)
Why can't I access it?
Because the derived class’ constructor won’t have been called, so the object may be in an invalid state. Some languages allow virtual-calls from a parent constructor but it’s still generally agreed to be a bad practice. TypeScript chose to disallow it.
This is mentioned in the documentation: https://www.typescriptlang.org/docs/handbook/classes.html
[...] each derived class that contains a constructor function must call
super()
which will execute the constructor of the base class. What’s more, before we ever access a property on this in a constructor body, we have to callsuper()
. This is an important rule that TypeScript will enforce.
The solution in in case is to pass pattern
as a parameter to Route
's constructor. If pattern
cannot be determined by the subclass’ constructor prior to calling the parent constructor then you need to rethink your design.
abstract class Route {
constructor(
private readonly pattern: string
)
{
console.log( pattern );
}
}
class Derived123 extends Route {
constructor() {
super( /*pattern:*/ "123" )
}
}
class Derived456 extends Route {
constructor() {
super( /*pattern:*/ "456" )
}
}