'How to correctly extend typescript class?

I get puzzled in the following problem. The last line m.removeChild(m.childNodes[0]) is complained by ts compiler. I have no idea whether childNodes: BaseNode[]; is correct in this case.

class BaseNode {
  childNodes: BaseNode[];
  constructor() {
    this.childNodes = [];
  }
  appendChild(node: BaseNode) {
    this.childNodes.push(node);
  }
}

class MyNode extends BaseNode {
  removeChild(node: MyNode): void {
    const index = this.childNodes.indexOf(node);
    if (index >= 0) {
      this.childNodes.splice(index, 1);
    }
  }
}

const m = new MyNode();
m.appendChild(new MyNode());

// Argument of type 'BaseNode' is not assignable to parameter of type 'MyNode'.
// Property 'removeChild' is missing in type 'BaseNode' but required in type 'MyNode'.(2345)
m.removeChild(m.childNodes[0]);


Solution 1:[1]

Thanks to @jcalz 's answer, I change all BaseNode type in class BaseNode to this, and it works in most cases, but using type this in the constructor is still unsupported by TS compiler.

class BaseNode {
  childNodes: this[];
  // Error in constructor
  // A 'this' type is available only in a non-static member of a class or interface.
  constructor(parentNode?: this) {
    if (parentNode) {
      parentNode.appendChild(this);
    }
    this.childNodes = [];
  }
  appendChild(node: this) {
    this.childNodes.push(node);
  }
}

class MyNode extends BaseNode {
  removeChild(node: this): void {
    const index = this.childNodes.indexOf(node);
    if (index >= 0) {
      this.childNodes.splice(index, 1);
    }
  }
}

const m = new MyNode();
m.appendChild(new MyNode());
// OK!
m.removeChild(m.childNodes[0]);

Finally, I changed the type of parentNode in constructor parameters to unknown, then check its type in constructor body. Maybe this is not the best method, but now I can only do something like that.

constructor(parentNode?: unknown) {
  if (parentNode instanceof BaseNode) {
    parentNode.appendChild(this);
  }
  this.childNodes = [];
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mick Fone