D3, Typescript - Аргумент типа 'this' не может быть назначен параметру типа 'BaseType' - PullRequest
0 голосов
/ 19 декабря 2018

У меня здесь stackbiltz - https://stackblitz.com/edit/lable-line-break-vaszab?file=src/app/app.component.ts

У меня есть гистограмма d3 и приложение Angular.

Метки оси x разделены на две строки с помощью функции, которая вызывается кактики оси z созданы

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'

Кто-нибудь знает, почему это происходит и как я могу это исправить.

1 Ответ

0 голосов
/ 20 декабря 2018

Компилятор определяет тип this внутри вашей функции insertLinebreak() как ваш класс StackedChartCompoent.Однако, взглянув на определения типов для d3.select(node), вы увидите, что он ожидает расширения узла BaseType, которое определено как

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 есть более идиоматический способ.Начиная с версии 2.0 , вы можете предоставить поддельный this параметр в качестве первого элемента в списке параметров вашей функции.Этот параметр сообщает компилятору, на что ссылается this внутри указанной функции.Ваш код может быть таким образом переписан как:

    private insertLinebreak(this: SVGTextElement) {
      let labels = d3.select(this);   // works
      // method body left untouched
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...