【问题标题】:d3.js and TypeScript compilation errord3.js 和 TypeScript 编译错误
【发布时间】:2017-11-12 08:47:07
【问题描述】:

我正在研究示例 Force Dragging I 并且已经能够使其与纯 JavaScript 一起使用。但是,我在尝试使用 TypeScript 时遇到了编译错误。

问题代码(去掉了多余的部分)是:

import * as d3 from "d3";

interface INode {
    id: string;
    group: number;
}

interface ILink {
    source: string;
    target: string;
    value: number;
}

interface IGraph {
    nodes: INode[];
    links: ILink[];
}

var svg = d3.select("svg");

d3.json("data/miserables.json", function (error, graph: IGraph) {

    var node = svg.append("g")
        .selectAll("circle")
        .data(graph.nodes) // Commenting this out, error goes away
        .enter().append("circle")
        .call(d3.drag() // Error here
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));
});

.call(d3.drag() 行导致以下 tsc 错误:

App.tsx(31,15):错误 TS2345:“DragBehavior”类型的参数不可分配给类型参数 '(选择:选择,...参数:任何[]) => 无效'。 参数“selection”和“selection”的类型不兼容。 “选择”类型不能分配给“选择”类型。 类型“BaseType”不可分配给类型“元素”。 类型“null”不能分配给类型“元素”。

类似d3 v4 drag and drop with TypeScript,改代码重选圈子没有报错:

var nodes =
  svg.append("g")
  .selectAll("circle")
  .data(graph.nodes)
  .enter().append("circle");

var circle = svg.selectAll("circle");
circle.call(d3.drag()
  .on("start", dragstarted)
  .on("drag", dragged)
  .on("end", dragended));

但是,当不使用类型时,这是不必要的。

我正在尝试在这里研究如何使用 TypeScript,以便定义具有适当类型的变量,或者编译所需的任何内容。

【问题讨论】:

  • 其他用户拥有same problem,但提供的答案未经验证。
  • 我可以用类似的方式解决这个错误,但不幸的是,在纯 js 中不需要重新选择。
  • 在缩放和 ZoomBehaviour 方面有同样的问题(以防有人搜索这些特定术语)

标签: typescript d3.js


【解决方案1】:

前言:

D3 模块的 TypeScript 定义在接口和方法中广泛使用泛型,最重要的是泛型用于控制 D3 操作的元素的类型,以及绑定的数据的类型到那些元素。

到你问题的核心:

(1) 创建拖动行为时,确保泛型对应元素类型,绑定数据类型对应要拖动的元素。在上述情况下,这应该暗示d3.drag<SVGCircleElement, INode>()

(2) 确保拖动事件处理程序(dragstarteddraggeddragended 具有匹配的调用签名,例如 function dragged(this: SVGCircleElement, d: INode) {...}(您只需指定 this-context 类型,如果您打算在回调中访问它。)

(3) 确保您应用拖动行为的选择具有相应的类型。 Selection 接口有四个泛型,其中前两个再次对应于所选元素的类型及其绑定数据的类型。 Selection 方法如 selectselectAlldataappend 都有对应于它们可能影响的“事物”的泛型。在data 的情况下,TS 可以根据传入调用的数据推断出泛型。对于其他提到的方法,您可能必须明确说明您“选择”或“附加”的是什么。对于上述情况,您可以考虑:

//...
.data<INode>(graph.nodes) // Commenting this out, error goes away
.enter()
.append<SVGCircleElement>("circle")
//...

上述更改应确保您的选择和拖动行为以类型安全的方式对齐。更多细节可以参考定义中的 cmets:

DragBehavior Definition 或相关定义测试hereSelection Definition。 由于所有这些 TS 定义都具有大量的 JSDoc cmets,因此一个好的 IDE 将具有悬停工具提示/预览,允许您在编写时查看它们。请注意 cmets 中引用 generics 的部分。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2017-10-27
    • 2016-01-11
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 2019-09-22
    • 2017-04-02
    相关资源
    最近更新 更多