我有一个实现访问者模式的简单类:
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
函数,该函数现在会返回一个number
。
我该如何实施这样的解决方案呢?
发布于 2019-05-29 03:36:35
是的,编译器不能自己解决这个问题。您可以帮助它做到这一点,但代价是复杂性更高( visit()
实现中的类型安全性更低)。我的建议是给visit()
一个generic签名,它的返回类型是基于polymorphic this
type of subclasses的conditional type:
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
也是如此。
希望这能有所帮助;祝你好运!
https://stackoverflow.com/questions/56348769
复制相似问题