Javascript - "Compound" Class Inheritance

Viewed 96

Not to be confused with inheriting from multiple classes.

Suppose there's a class, Player, with its own methods and properties:

class Player {
//...
}

Next, suppose there's a class which extends from Player, with its own special properties

class SpecificPlayer extends Player {
  constructor() {
    super();
    this.foo = "bar";
  }
}

Now suppose there's another class, Core, with a property of type Player[] (types are defined through JSDoc-style comments in VSCode), and a method which returns a portion of that array.

class Core {
  constructor(players) {
    /** @type {Player[]} */
    this.players = players;
  }

  getSomePlayers() {
    return this.players.filter(...);
  }
}

Finally, let there be a class which extends from Core, with a constructor and method as follows:

class SpecificClass extends Core {
  /** @param {SpecifcPlayer[]} players */
  constructor(players) {
    super(players);
  }

  doThing() {
    console.log(this.players[0].foo);
    this.getSomePlayers().forEach(p => console.log(p.foo));
  }
}

Now, if the following main body code is ran:

const SpecificInstance = new SpecificClass([new SpecificPlayer(), new SpecificPlayer()]);
SpecificInstance.doThing();

Everything is fine and dandy -- "bar" is printed successfully for all log statements.

However, when writing the code (specifically the body of doThing), VSCode Intellisense would only recognize this.players as a type of Player, meaning it wouldn't recognize the property foo. How would I go about writing the classes such that the VSCode autocomplete/Intellisense recognizes the correct type of this.players, and each method in Core which uses this.players also returns the correct type of SpecificPlayer? Realistically, there are several classes extending from Core, some with their own special variation on Player. As such, the types returned should be that which was provided originally to the constructor.

(Or is there a better way to organize/format my code?)

0 Answers
Related