您不能直接将Parent 转换为Child,因为编译器无法知道您的Parent 实例确实是Child。使用类型保护而不是强制类型转换:
class Parent {
prop: string|null = null;
isChild(): this is Child {
return (this as any).otherProp !== undefined;
}
}
class Child extends Parent
{
otherProp: string|null = null;
}
function test(p: Parent) {
if (p.isChild()) {
console.log(p.otherProp);
}
}
在受保护的if 内部,编译器现在知道p 是Child,在它外部p 仍然只是Parent。
或者更好的是,覆盖子类中的守卫,您可以完全避免进行任何类型转换:
class Parent {
prop: string|null = null;
isChild(): this is Child {
return false;
}
}
class Child extends Parent
{
otherProp: string|null = null;
isChild(): this is Child { return true; }
}
function test(p: Parent) {
if (p.isChild()) {
console.log(p.otherProp);
}
}
您是对的,但是我没有回答这个问题是 Typescript 作者的错误还是故意的。我的猜测是他们试图捕捉可能的错误,但我还没有设法找到可以确认或否认这种确切行为的解释。
使原始代码工作的另一种方法是在 castToChild 方法中明确告诉 typescript this 的类型:
class Parent {
prop: string|null = null;
castToChild(this: Parent): Child{
return this as Child;
}
}
class Child extends Parent
{
otherProp: string|null = null;
}
function foo() {
let p: Parent = new Child();
let c = p.castToChild();
console.log(c.otherProp);
}
这仍然只是做双重演员,但可能看起来更干净一些。然而,它仍然显示出行为的奇怪之处,因为没有显式 this 参数 this 是 Parent 类型但不能直接转换,使用显式参数可以转换它。