在TypeScript中的继承类方法中动态返回继承的类类型

时间:2018-02-04 02:06:23

标签: typescript inheritance

我有一个班级

class Node {
   children: Node[];
}

由其他几个类继承

class Block extends Node {
  // ...
}

在所有继承的类中,我希望有一个名为replaceChild的函数:

const block = new Block();
block.replaceChild(oldChild, newChild);

我不想在所有继承的类中实现此函数(duh!)。这里的线索是我的类是不可变的,所以我没有改变类,而是想要返回一个带有更改children的新实例。问题是,我想在replaceChild中实现的函数Node不应该返回Node实例,而是返回继承类的实例:

class Node {
  children: Node[];
  replaceChild(oldChild, newChild): Node {
    // ...
    return new Node(/* ... */)
  }
}

class Block extends Node {
  // ...
}

const block = new Block();
const newMutatedBlock: Block = block.replaceChild(oldChild, newChild);

我正在使用TypeScript。如何告诉TypeScript(每次没有进行类型转换)replaceChild节点上的方法Block返回Block而不是Node

1 个答案:

答案 0 :(得分:4)

您正在寻找polymorphic this,这是一种与this对象相对应的类型。而不是说replaceChild()返回类型Node,而是说它返回类型this

请注意,您不能在new Node()的实现中调用replaceChild(),因为这不会正确创建子类。幸运的是,类的实例包含对其构造函数的引用,因此您可以调用new this.constructor()。不幸的是,除了this.constructor之外,TypeScript对Function一无所知。幸运的是,您可以声明this.constructor具有类型new()=>this并安全使用它。 (由您来正确声明参数类型并确保所有子类构造函数采用相同的参数类型)。这是它的外观:

class Node {
    children: Node[];
    "constructor": new (/* ... */) => this;
    replaceChild(oldChild, newChild): this {
        // ...
        return new this.constructor(/* ... */)
    }
}

我不确定oldChildnewChild是否也应该是this,或Node,或者是什么。你必须决定。

现在测试:

class Block extends Node {
    // ...
}

const block = new Block();
const newMutatedBlock: Block = block.replaceChild(oldChild, newChild);

这有效(假设oldChildnewChild存在并且是正确的类型),因为Block.replaceChild()会返回Block而不只是Node。< / p>

The Playground

中查看它

希望有所帮助;祝你好运!