如何创建仅包含特定类和该类子级的字典变量

时间:2018-12-24 10:45:59

标签: typescript

我需要构建一棵树,其中树的每个节点都可以是基节点的实例或基节点的子节点。

我有一个类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的子级。

1 个答案:

答案 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'));