admin管理员组

文章数量:1429729

I am trying to add a simple D3.js bar chart to a Ionic 2 project.

I imported d3 and installed the type definitions as follows:

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

I added the following in the TS file for the page:

import * as d3 from 'd3'

When running ionic serve it finds the definition file with no problem. When I try a simple chart example such as the following, it also works with no problem:

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");});

However, when I try the following bar chart example (found here), it doesn't work:

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); });
});

I get a list of undefined typescript errors (even though the definition file for D3 v4 was successfully imported):

[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 

I am trying to add a simple D3.js bar chart to a Ionic 2 project.

I imported d3 and installed the type definitions as follows:

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

I added the following in the TS file for the page:

import * as d3 from 'd3'

When running ionic serve it finds the definition file with no problem. When I try a simple chart example such as the following, it also works with no problem:

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");});

However, when I try the following bar chart example (found here), it doesn't work:

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); });
});

I get a list of undefined typescript errors (even though the definition file for D3 v4 was successfully imported):

[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 
Share Improve this question edited Dec 15, 2016 at 1:28 Martin asked Dec 15, 2016 at 1:01 MartinMartin 1,0902 gold badges16 silver badges28 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

As a workaround I just used declare var d3: any; in the model file (src/pages/page1/page1.ts in this case). To use this method I had to manually insert <script src="d3.v3.min.js"></script> in src/index.html instead of using import via Node.

Short answer is that you haven't told typescript the types of your arguments in your callback. How you do that is often tricky, so what I find useful is to look at the unit tests for the type-ings files. For this case see here. Untested but it'll end up looking something like this:

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>) {

  ...

}

本文标签: javascriptquotPropertydoes not exist ontypequot D3js typescript errors in Ionic 2 projectStack Overflow