Foobar
Foobar

Reputation: 8487

Typescript - call abstract method from abstract constructor or provide equivalent functionality

In Typescript - abstract methods cannot be called from within abstract constructors (the code will compile, but will crash at runtime).

Take the following example where the code crashes:

abstract class Puzzle {


    addState = () => {
         let data = this.createStateData()
         //Perform a operation with data 
    }

    abstract createStateData: () => Object

    protected constructor() {
        //The code crashes here because createStateData
        //has not been defined yet
        this.addState()
     }

}

class RiverPuzzle extends Puzzle {

    createStateData = (): Object => {
         return 'Foo'
    }

    constructor() { 
        super()
        //this.addState()
    }

}

In this particular example, the problem can be solved by uncommenting the line in the constructor of the RiverPuzzle class and commenting the offending line in the constructor of the abstract class.

However, the solution is suboptimal because there are many classes extending the abstract class Puzzle and I don't want to manually add this.addState() to the constructor of every single subclass.

What is a more efficient alternative?

Upvotes: 2

Views: 7373

Answers (1)

jcalz
jcalz

Reputation: 329308

You are using arrow functions as methods, which is generally discouraged. It does weird things with this, and each instance of your class will have its own method as opposed to having just one method on the prototype. Unless you have some good reason, I suggest you use prototype methods (not using arrow function notation), like this:

abstract class Puzzle {
    addState() {
         let data = this.createStateData()
         //Perform a operation with data 
    }

    abstract createStateData(): Object

    protected constructor() {
        this.addState()
     }
}

class RiverPuzzle extends Puzzle {
    createStateData() {
         return 'Foo'
    }

    constructor() { 
        super()            
    }
}

That should hopefully work more as you expect.

Upvotes: 3

Related Questions