我正在尝试做我认为是多态this
的“教科书”用例,但它无法正常工作,我无法理解这一点。想象一下,我有一些可复制的abstract
基类,例如:
abstract class X {
abstract clone(): this;
}
现在我想实现一个提供clone
实现的基类:
class Y extends X {
constructor(private x: number) { super() }
clone(): this { return new Y(this.x + 1); }
}
当我这样做时,我收到一条错误Type Y is not assignable to type 'this'
。我完全糊涂了。我想在这里传达的是类型约束,如果X
的子类调用了它的clone
方法,那么你将获得的东西的类型将与子类型相同。这不是多态this
的确切含义吗?我在这里做错了什么?
Here is a link到TypeScript playground中的此代码。
答案 0 :(得分:2)
我已经将artem的答案标记为正确的答案,因为他似乎是正确的,因此无法以100%安全的方式执行此操作。
但是,有一种方法可以让编译器强制执行我想要的类型约束。所以,我决定将这个答案包括在内,以防人们对它有用。我的方法的唯一缺点是它确实有点不安全,因为artem指出的原因,即有人可以扩展你的类而不提供clone
的实现,并创建一个返回值不会真正的情况是你声称的。
我的解决方案是添加演员。同样,这一般是不安全的。但是,如果你从不延伸到课程,它就可以正常工作。所以我的解决方案是:
class Y extends X {
constructor(private x: number) { super() }
clone(): this {
return new Y(this.x + 1) as this;
}
}
您可以看到编译here的完整版本。
答案 1 :(得分:2)
不,就像现在的情况一样,它不是这种类型的受支持用例。具有this
返回类型的方法应返回派生类的实例,即使此方法未在派生类中重写 - 请参阅code in this answer以获得证明这一点的示例。
换句话说,给定abstract clone(): this
声明,即使Z没有覆盖clone
本身,此代码也必须有效,但是您在clone
中实施Y
会破坏它
class Z extends Y {
f() {
let c: Z = this.clone();
}
}
因此看起来this
返回类型的方法应始终为return this
。
更新:我在github上找到了一个open issue这个用例,标记为“接受拉取请求”。我不确定他们是否真的打算支持它,或者计划以其他方式在他们的编译器中修复cloneNode
。