我在使用SimulationLinkDatum类型时遇到问题。我创建了两个实现SimulationNodeDatum和SimulationLinkDatum的Node和Link类。当我尝试使用SimulationLinkDatum时,typescript说d.source.x,d.targe.x等等typescript说“属性'x'在类型'string | number | Node'上不存在。“
据我所知,SimulationLinkDatum接受form
表示源节点属性和目标节点属性,如果使用数字或字符串,它将被变换为SimulationNodeDatum。这只是我们必须接受的东西,还是有更好的方法来使用这些接口?
由于
style
答案 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
- 子句中使用类型缩小,而不创建可重复使用的自定义类型保护。
鉴于接口当前的定义方式,这些是访问变异属性中对象的关键方法。