我需要构建一棵树,其中树的每个节点都可以是基节点的实例或基节点的子节点。
我有一个类BaseNode
,该类具有属性nodes
,该属性应包含BaseNode的实例或BaseNode的子代。
我写了一个简单的代码,但是编译器在方法Type 'BaseNode' is not assignable to type 'T'.
getNodeById
interface NodeDictionary <T extends BaseNode> {
[index: string]: T;
};
class BaseNode {
private nodes: NodeDictionary<BaseNode> = {};
constructor(private id: string, private name: string) {
}
getId() {
return this.id;
}
append<T extends BaseNode>(node: T) {
this.nodes[node.getId()] = node;
}
getNodeById<T extends BaseNode>(id: string): T {
return this.nodes[id];
}
}
class ExtendBaseNode extends BaseNode {
someMethod() {
}
}
let a = new BaseNode('A', 'My name is A');
let b = new ExtendBaseNode('B', 'My name is B');
a.append<ExtendBaseNode>(b);
如何向编译器解释道具nodes
可能包含BaseNode的实例或BaseNode的子级。
答案 0 :(得分:1)
您对该特定方法的签名与返回的内容冲突。由于nodes
基本上严格包含BaseNode
对象,因此无法自动将其类型转换为ExtendBaseNode
之类的超类。尽管T
可以是BaseNode
,但也可以是ExtendBaseNode
。
我建议进行以下更改
getNodeById<T extends BaseNode>(id: string): T {
return this.nodes[id] as T;
}
它将首先将返回值转换为T
类型。
在假定类型正确的前提下,此代码可以按预期工作:
let a = new BaseNode('A', 'My name is A');
let b = new ExtendBaseNode('B', 'My name is B');
a.append(b);
console.log(a.getNodeById<ExtendBaseNode>('B'));