我有一个实现访问者模式的简单类:
abstract class MyNode {};
class MyNodeA extends MyNode {};
class MyNodeB extends MyNode {};
abstract class NodeVisitor {
abstract visitMyNodeA(node: MyNodeA): unknown;
abstract visitMyNodeB(node: MyNodeB): unknown;
public visit(node: MyNode) {
if(node instanceof MyNodeA) {
return this.visitMyNodeA(node);
} else if(node instanceof MyNodeB) {
return this.visitMyNodeB(node);
} else {
throw new Error('Unknown node type on visitor');
}
}
}
以及以后,我想在实现NodeVisitor
class MyNodeVisitor extends NodeVisitor {
visitMyNodeA(node: MyNodeA): number {
return 1;
}
visitMyNodeB(node: MyNodeB): number {
return this.visit(new MyNodeA()) + 1;
}
}
但这会产生错误,因为TypeScript编译器没有意识到对visit
类型的参数MyNodeA
的调用重定向到visitMyNodeA
函数,该函数现在返回{{1 }}。
我将如何实施这样的解决方案?
答案 0 :(得分:1)
是的,编译器无法自行解决。您可以通过增加复杂性(并降低visit()
实现中的类型安全性)来帮助它。我的建议是给visit()
一个generic签名,其返回类型是一个基于conditional type的polymorphic this
type of subclasses:
abstract class MyNode {myNode = "myNode"}
class MyNodeA extends MyNode {a = "a"}
class MyNodeB extends MyNode {b = "b"}
abstract class NodeVisitor {
abstract visitMyNodeA(node: MyNodeA): unknown;
abstract visitMyNodeB(node: MyNodeB): unknown;
// call signature
public visit<T extends MyNode>(
node: T
): T extends MyNodeA ? ReturnType<this["visitMyNodeA"]> :
T extends MyNodeB ? ReturnType<this["visitMyNodeB"]> :
never;
// implementation signature is wider
public visit(node: MyNode): unknown {
if (node instanceof MyNodeA) {
return this.visitMyNodeA(node);
} else if (node instanceof MyNodeB) {
return this.visitMyNodeB(node);
} else {
throw new Error("Unknown node type on visitor");
}
}
}
class MyNodeVisitor extends NodeVisitor {
visitMyNodeA(node: MyNodeA): number {
return 1;
}
visitMyNodeB(node: MyNodeB): number {
return this.visit(new MyNodeA()) + 1;
}
}
行得通吗?这个想法是让您带领编译器进行以下分析:如果您传递MyNodeA
,则visit()
将返回this.visitMyNodeA(node)
的结果,而对MyNodeB
的返回结果也是相同的。
希望有所帮助;祝你好运!