1

Я пытаюсь добавить простую диаграмму D3.js в проект Ionic 2.«Свойство _ не существует на _ type» Ошибки типа D3.js в проекте Ionic 2

Я импортировал d3 и установил определение типов следующим образом:

npm install d3 
npm install @types/d3 --save-dev --save-exact 

Я добавил следующее в файле TS для страницы:

import * as d3 from 'd3' 

При запуске ionic serve он находит файл определение с без проблем. Когда я пытаюсь простой пример диаграммы, такие как следующие, она также работает без проблем:

var sampleSVG = d3.select("#chart") 
    .append("svg") 
    .attr("width", 100) 
    .attr("height", 100);  

sampleSVG.append("circle") 
    .style("stroke", "gray") 
    .style("fill", "white") 
    .attr("r", 40) 
    .attr("cx", 50) 
    .attr("cy", 50) 
    .on("mouseover", function(){d3.select(this).style("fill", "aliceblue");}) 
    .on("mouseout", function(){d3.select(this).style("fill", "white");}); 

Однако, когда я пытаюсь следующий пример гистограммы (найденный here), она не работает:

var svg = d3.select("svg"), 
    margin = {top: 20, right: 20, bottom: 30, left: 40}, 
    width = +svg.attr("width") - margin.left - margin.right, 
    height = +svg.attr("height") - margin.top - margin.bottom; 

var x = d3.scaleBand().rangeRound([0, width]).padding(0.1), 
    y = d3.scaleLinear().rangeRound([height, 0]); 

var g = svg.append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

d3.tsv("data.tsv", function(d) { 
    d.frequency = +d.frequency; 
    return d; 
}, function(error, data) { 
    if (error) throw error; 

    x.domain(data.map(function(d) { return d.letter; })); 
    y.domain([0, d3.max(data, function(d) { return d.frequency; })]); 

    g.append("g") 
     .attr("class", "axis axis--x") 
     .attr("transform", "translate(0," + height + ")") 
     .call(d3.axisBottom(x)); 

    g.append("g") 
     .attr("class", "axis axis--y") 
     .call(d3.axisLeft(y).ticks(10, "%")) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", "0.71em") 
     .attr("text-anchor", "end") 
     .text("Frequency"); 

    g.selectAll(".bar") 
    .data(data) 
    .enter().append("rect") 
     .attr("class", "bar") 
     .attr("x", function(d) { return x(d.letter); }) 
     .attr("y", function(d) { return y(d.frequency); }) 
     .attr("width", x.bandwidth()) 
     .attr("height", function(d) { return height - y(d.frequency); }); 
}); 

получить список неопределенных ошибок машинописи (даже если файл определения для D3 v4 был успешно импортирован):

[11:54:14] typescript: src/pages/page1/page1.ts, line: 35 
      Property 'frequency' does not exist on type 'DSVRowString'. 

     L34: d3.tsv("data.tsv", function(d) { 
     L35: d.frequency = +d.frequency; 
     L36: return d; 

[11:54:14] typescript: src/pages/page1/page1.ts, line: 35 
      Property 'frequency' does not exist on type 'DSVRowString'. 

     L34: d3.tsv("data.tsv", function(d) { 
     L35: d.frequency = +d.frequency; 
     L36: return d; 
[11:54:14] typescript: src/pages/page1/page1.ts, line: 40 

      Property 'letter' does not exist on type 'DSVRowString'. 

     L40: x.domain(data.map(function(d) { return d.letter; })); 
     L41: y.domain([0, d3.max(data, function(d) { return d.frequency; })]); 

[11:54:14] typescript: src/pages/page1/page1.ts, line: 41 
      The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type 
      arguments explicitly. Type argument candidate 'DSVRowString' is not a valid type argument because it is not 
      a supertype of candidate 'string'. 

     L40: x.domain(data.map(function(d) { return d.letter; })); 
     L41: y.domain([0, d3.max(data, function(d) { return d.frequency; })]); 
[11:54:14] typescript: src/pages/page1/page1.ts, line: 59 

      Argument of type 'DSVParsedArray<DSVRowString>' is not assignable to parameter of type '(this: BaseType, 
      datum: {}, index: number, groups: ArrayLike<BaseType> | BaseType[]) => {}[]'. Type 
      'DSVParsedArray<DSVRowString>' provides no match for the signature '(this: BaseType, datum: {}, index: 
      number, groups: ArrayLike<BaseType> | BaseType[]): {}[]' 

     L58: g.selectAll(".bar") 
     L59: .data(data) 
     L60: .enter().append("rect") 

[11:54:14] transpile failed 

ответ

1

В качестве обходного пути я просто использовал declare var d3: any; в файле модели (src/pages/page1/page1.ts в данном случае). Чтобы использовать этот метод, мне пришлось вручную вставить <script src="d3.v3.min.js"></script> в src/index.html вместо использования импорта через узел.

0

Короткий ответ заключается в том, что вы не указали машинописные типы ваших аргументов в своем обратном вызове. Как вы это делаете, часто сложно, поэтому то, что я считаю полезным, - это посмотреть на модульные тесты для файлов типов. Для этого случая см. here. Непроверенная, но это будет в конечном итоге выглядит примерно так:

interface ChartData { 
    frequency: string; 
    letter: number;  
} 

d3.tsv("data.tsv", function(d) { 
    let rr: d3Dsv.DSVRowString = d; 
    let pr: ChartData; 

    pr = { 
    frequency: +rr['frequency'], 
    letter: rr['letter'] 
    }; 

    return pr; 
}, function(error, data:Array<ChartData>) { 

    ... 

} 
+0

Это потребовало бы справедливой работы с библиотеками, связанными с d3, которые я хотел импортировать, поэтому я просто использовал решение в своем ответе. Вы теряете часть безопасности, но удобны, когда вам это нужно быстро. – Martin

Смежные вопросы