我有一个实现访问者模式的简单类:
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
.
我将如何实施这样的解决方案?
是的,编译器自己无法解决这个问题。您可以帮助它做到这一点,但代价是更加复杂(以及visit()
实现内部的类型安全性较低)。我的建议是给出visit()
一个通用签名,其返回类型是基于子类的多态类型的条件类型:this
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
。
希望有所帮助;祝你好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句