Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compilation errors when drawing a piechart using d3.js and TypeScript

I am attempting to draw a pie chart using the d3.js library and TypeScript. I have the following code:

"use strict";
module Chart {
  export class chart {

    private chart: d3.Selection<string>;
    private width: number;
    private height: number;
    private radius: number;
    private donutWidth: number;
    private dataset: { label: string, count: number }[];
    private color: d3.scale.Ordinal<string, string>;

    constructor(container: any) {
      this.width = 360;
      this.height = 360;
      this.radius = Math.min(this.width, this.height) / 2;
      this.donutWidth = 75;

      this.dataset = [
        { label: 'Road', count: 5500 },
        { label: 'Bridge', count: 8800 },
        { label: 'Tunnel', count: 225 },
      ];

      this.color = d3.scale.category10();

      this.init(container);

    }

    private init(container) {
      this.chart = d3.select(container).append('svg')
        .attr('width', this.width)
        .attr('height', this.height)
        .append('g')
        .attr('transform', 'translate(' + (this.width / 2) +
        ',' + (this.height / 2) + ')');
    }

    draw() {

      var arc = d3.svg.arc()
        .innerRadius(this.radius - this.donutWidth)  // NEW
        .outerRadius(this.radius);

      var pie = d3.layout.pie()
        .sort(null);

      var path = this.chart.selectAll('path')
        .data(pie(this.dataset.map(function(n) {
          return n.count;
        })))
        .enter()
        .append('path')
        .attr('d', arc)
        .attr('fill', function(d, i) {
          return Math.random();
        });
    }

  }
}

The code does not compile with the error:

 Argument of type 'Arc<Arc>' is not assignable to parameter of type '(datum: Arc<number>, index: number, outerIndex: number) => string | number | boolean'.
>>   Types of parameters 'd' and 'datum' are incompatible.
>>     Type 'Arc' is not assignable to type 'Arc<number>'.
>>       Property 'value' is missing in type 'Arc'.   

The compilation error is showing up when I try to add the d attribute to each of the path elements on my svg:

var path = this.chart.selectAll('path')
        .data(pie(this.dataset.map(function(n) {
          return n.count;
        })))
        .enter()
        .append('path')
        .attr('d', arc)
        .attr('fill', function(d, i) {
          return Math.random();
        });

According to the documentation an arc is "is both an object and a function." and I see that I can access it by calling arc(datum[, index]), by just hardcoding arc[0] for example. When I do this my compilation error goes away but the d attribute of each path element in the svg is missing and I end up with an svg like:

    <svg height="360" width="360">
      <g transform="translate(180,180)">
         <path fill="0.35327279710072423"></path>
         <path fill="0.6333000506884181"></path>
         <path fill="0.9358429045830001"></path>
      </g>
    </svg>

I've had the code running as pure JavaScript with no problems.

like image 556
Matt Watson Avatar asked Oct 13 '15 16:10

Matt Watson


People also ask

Can you use D3 with TypeScript?

Although D3 is a JavaScript library, we will use TypeScript because it handles data and data types more efficiently than plain old JavaScript. This tutorial will show you how to create visualizations using D3 and TypeScript.

How will you invoke the arc path generator in d3js?

d3. arc() returns a generator that when called automatically generates and returns a string of characters that can be assigned to the d attribute of a path element to define an arc, circle, or annulus. To create an arc generator simply call d3. arc() .


2 Answers

Try to replace

.attr('d', arc)   

with

.attr('d', <any>arc)  

This hides the compiler error on my computer but if that actually work... Well, I don't know.

My understanding of the problem is that you provide .data function with number values and TypeScript compiler expects that .attr will contain also a number but you provide an arc instead.

like image 99
Martin Vseticka Avatar answered Nov 15 '22 18:11

Martin Vseticka


Came here because I had the same problem with D3 v5!

Solution: Use the PieArcDatum interface (Very strange name in my opinion!!!)

Details:

import { PieArcDatum } from 'd3-shape';

... 

type Population = { time: string, population: number; };

...

const svg = element.append("g")
    .attr("transform", `translate(${300}, ${160})`)
;

const pie = d3.pie<Population>()
    .sort(null)
    .value((record) => record.population);

const path = d3.arc<PieArcDatum<Population>>()
    .innerRadius(0)
    .outerRadius(150)
;

// Beim selectAll kommt eine leere Selection zurück da es noch keinen Circle gibt
const data = pie(worldPopulation);
const arch = svg.selectAll(".arc")
    .data(data)
    .enter()
    .append("g")
        .attr("class", "arc")
;

arch.append('path')
    .attr("d", path)
;


Sidenote: I'm using WebStorm, WS was not able to find (autoimport) PieArcDatum - I had to import it manually...

like image 45
Mike Mitterer Avatar answered Nov 15 '22 19:11

Mike Mitterer