最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - "Property _ does not exist on _ type" D3.js typescript errors in Ionic 2 project - Stack Overflow

programmeradmin0浏览0评论

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

  ...

}
发布评论

评论列表(0)

  1. 暂无评论