基类返回对扩展类类型不匹配的引用

时间:2018-06-17 09:45:10

标签: typescript

我有一个基类的简化版本,它应该是树结构的一个节点,并保存对它的父级的引用。

class Node {
  parent: Node;

  setParent(a: Node) {
    this.parent = a;
  }

  getParent(): Node {
    return this.parent;
  }
}

派生类为基本节点添加了更多功能

class NamedNode extends Node {
  name: string;

  setName(name: string) {
    this.name = name;
  }
}

我使用派生类创建我的小树,并通过调用setParent存储对子项中父项的引用,然后通过调用getParent从子项中检索父项。

const parent = new NamedNode();

const child = new NamedNode();
child.setParent(parent);

const parentOfChild = child.getParent();

parentOfChild.setName('foo');

当我对检索到的父级进行调用setName时,即使它是NamedNode的实例,TypeScript也会抛出错误

  

Property' setName'类型'节点'。

上不存在

我可以理解,因为方法签名getParent(): Node明确定义它只返回Node的实例,并且它没有setName方法。

我的问题是如何让getParent返回Node的实例,以便我知道返回值将具有Node的方法,但同时它应该是开放的扩展所以我可以在没有TypeScript抱怨的情况下对返回的值调用后代方法。我的目标是每个后代节点类都有Node方法,然后这些后代类的实例可以作为Node引用在基础parent类中使用。我还想避免在派生类中覆盖Node方法来更新Node方法签名,因为继承方法重用的重点将会消失。

1 个答案:

答案 0 :(得分:1)

您可以使用this作为类型,表示当前类的类型,以便派生类parent中的类型与派生类的类型相同:

export class Node {
    parent: this;

    setParent(a: this) {
        this.parent = a;
    }

    getParent(): this {
        return this.parent;
    }
}

class NamedNode extends Node {
    name: string;

    setName(name: string) {
        this.name = name;
    }
}


const parent = new NamedNode();

const child = new NamedNode();
child.setParent(parent);

const parentOfChild = child.getParent();

parentOfChild.setName('foo');

此语言的此功能称为多态,您可以在docsPR

中详细了解该功能