首页 > 解决方案 > 基类返回对扩展类类型不匹配的引用

问题描述

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

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 也会引发错误

类型“节点”上不存在属性“setName”。

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

我的问题是如何让getParentreturn 的一个实例,Node所以我会知道返回值将具有 a 的方法Node,但同时它应该对扩展开放,这样我就可以在没有返回值的情况下调用后代方法打字稿抱怨。我的目标是每个后代节点类都有Node方法,然后这些后代类的实例可以在基Node类中用作parent参考。我还想避免Node在派生类中重写方法来更新Node方法签名,因为继承方法重用的全部意义将不复存在。

标签: typescript

解决方案


您可以将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');

该语言的此功能称为多态 this,您可以在文档PR中阅读更多信息


推荐阅读