【问题标题】:D3, Typescript - Argument of type 'this' is not assignable to parameter of type 'BaseType'D3,Typescript - 'this' 类型的参数不可分配给'BaseType' 类型的参数
【发布时间】:2018-12-19 16:28:55
【问题描述】:

我在这里有 stackbiltz - https://stackblitz.com/edit/lable-line-break-vaszab?file=src/app/app.component.ts

我在 Angular 应用中有一个 d3 条形图。

使用在创建 z 轴刻度时调用的函数将 x 轴标签分成两行

private insertLinebreak(d) {

    let labels = d3.select(this);
    let words = d;
    console.log("Label:", labels.html());
    labels.text('');

    let index = words.indexOf(' ', words.indexOf(' ') + 1)
    let title = words.substr(0, index)
    let subtitle = words.substr(index + 1)

    let tspantitle = labels.append('tspan').text(title)
    let tspansubtitle = labels.append('tspan').text(subtitle)
    tspantitle
      .attr('x', 0)
      .attr('dy', '15')
      .attr('class', 'x-axis-title');
    tspansubtitle
      .attr('x', 0)
      .attr('dy', '16')
      .attr('class', 'x-axis-subtitle');

  };

函数使用'this'来选择调用函数的'g'(但在d3中我认为它选择了整个svg)

此代码在 stackblitz 中有效,但在我的实际代码中出现错误

Argument of type 'this' is not assignable to parameter of type 'BaseType'.

我知道这不是很有帮助

我认为这与 Typescript 及其处理“this”的方式有关

有谁知道为什么会发生这种情况以及我该如何解决这个问题。

【问题讨论】:

  • 这听起来像是与 TypeScript 相关的 type 错误,而且 D3 不是 TypeScript 库。您可以通过将npm install @types/d3 --save 添加到您的项目来安装类型支持。 BaseType 是 D3 类型的一部分,您可以查看上述包中的 .d.ts 文件,以了解 d3.select 的类型签名是什么。您需要将 this 转换为该类型,但这并不意味着您的代码可以正常工作。这只是 TypeScript 的输入错误。
  • 是的,我认为它与 Typescript 有关。我在应用程序中安装了 d3 类型。实际的应用程序可以工作,但这个错误意味着我无法将其推送到生产环境。

标签: angular typescript d3.js


【解决方案1】:

编译器将this 的类型推断为insertLinebreak() 函数中的类StackedChartCompoent。但是,查看d3.select(node)type definitions,您可以看到它期望节点扩展BaseType,即defined

export type BaseType = Element | EnterElement | Document | Window | null;

因为你的类显然没有扩展这个 BaseType 你得到了错误。

基本上有两种解决方法:

  1. 如果你只在一个地方需要insertLinebreak()方法,即作为.each()的回调,你可以把它做成一个函数表达式,然后直接作为参数传递给.each()

    .each(function() {
      let labels = d3.select(this);   // works
      // ...the original method's body
    })
    

    这是可行的,因为编译器现在知道此函数的单个入口点,并且可以推断 this 的类型,因为 .each() 使用 Function.prototype.call()this 绑定到节点。

    但请记住,您必须使用经典的函数表达式来支持 ES6 箭头函数,因为这会使 this 再次指向其词法范围而不是节点。

  2. 幸运的是,TypeScript 本身内置了一种更惯用的方式。由于version 2.0,您可以提供一个假的this parameter 作为函数参数列表中的第一项。此参数告诉编译器this 在所述函数内部指的是什么。因此,您的代码可以重写为:

    private insertLinebreak(this: SVGTextElement) {
      let labels = d3.select(this);   // works
      // method body left untouched
    }
    

【讨论】:

    【解决方案2】:

    如果仍然有人找不到解决方案,请尝试一下!!!

    private insertLinebreak(d,i,n){
      //d is your data
      //i is the current index
      //n is the current node
      let labels = d3.select(this); // won't work
      let labels = d3.select(n[i]); // works
     }
    

    编码愉快!!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-17
      • 2020-03-26
      • 2019-01-03
      • 2023-01-18
      • 2020-12-23
      • 2013-11-03
      • 2019-02-25
      • 2020-06-19
      相关资源
      最近更新 更多