如何在d3中使用SimulationLinkDatum和SimulationNodeDatum

时间:2017-04-29 13:35:17

标签: angular typescript d3.js

我在使用SimulationLinkDatum类型时遇到问题。我创建了两个实现SimulationNodeDatum和SimulationLinkDatum的Node和Link类。当我尝试使用SimulationLinkDatum时,typescript说d.source.x,d.targe.x等等typescript说“属性'x'在类型'string | number | Node'上不存在。

据我所知,SimulationLinkDatum接受form表示源节点属性和目标节点属性,如果使用数字或字符串,它将被变换为SimulationNodeDatum。这只是我们必须接受的东西,还是有更好的方法来使用这些接口?

由于

style

1 个答案:

答案 0 :(得分:1)

正如您正确指出的那样, d3-force 的TypeScript定义反映了改变实际JS实现中固有的节点和链接数据结构的方法。

具体来说,对于SimulationLinkDatum<NodeDatum extends SimulationNodeDatum>接口,建议的做法是使用自定义类型保护,例如:

function isNodeObject<T>(node: number | string| T): node is T {
    return typeof node !== 'number' && typeof node !== 'string';
}

然后可以像往常一样使用TypeScript的类型缩小,例如在你的情况下:

private createPathString(d: SimulationLinkDatum<Node>) {
  if (isNodeObject(d.source) && isNodeObject(d.target)) {
    return 'M' + d.source.x + ',' + d.source.y + 'L' + d.target.x + ',' + d.target.y;
  } else {
    return '';
  }
}

虽然这是最可重复使用的方法,但在某些情况下,以下两种选择可能更合适:

(1)如果已知只在已经初始化的链接上调用给定的代码段,则可以简单地转换(<SimNode>d.source).x。对转换节点对象使用局部变量可以提高下游可读性。

(2)直接在if - 子句中使用类型缩小,而不创建可重复使用的自定义类型保护。

鉴于接口当前的定义方式,这些是访问变异属性中对象的关键方法。