使用D3.js,TypeScript和Angular绘制饼图时出现编译错误

时间:2016-02-15 15:26:11

标签: javascript angularjs d3.js typescript

我正在尝试显示饼图并且它实际上正常工作,即使我收到TypeScript编译错误:Argument of type '(d: any) => {}' is not assignable to parameter of type 'datum: Arc<number>, index: number, outerIndex: number) => number | string | boolean'. Type '{}' is not assignable to type 'number | string | boolean'. Type '{}' is not assignable to type 'boolean'.

过去两年我一直在使用TypeScript,但上面的一行让我头晕目眩。我不知道发生了什么,我尝试了一些事情,但到目前为止没有任何工作。

这是实际绘制饼图的代码:

function drawChart(){
            var width = 960,
                height = 500,
                radius = Math.min(width, height) / 2;

            var colourValues = d3.scale.ordinal().range(d3.values(that.ColoursService.colours));

            var arc = d3.svg.arc()
                .outerRadius(radius - 10)
                .innerRadius(radius - 70);

            var pie = d3.layout.pie()
                .sort(null)
                .value(function(d: any) {return d.quantity});

            var svg = d3.select('.pie-chart').append('svg')
                .attr('width', width)
                .attr('height', height)
                .append('g')
                .attr('transform', 'translate(' + width / 2 + ',' + height/2 + ')');

            var g = svg.selectAll('.arc')
                .data(pie(data))
                .enter().append('g')
                .attr('class', 'arc');

            g.append('path')
                .attr('d', <any>arc)
                .attr('fill', function(d: any) {
                    return colourValues(d.data.category); 
                });
        }

这是打字稿突出显示错误的地方,波浪线出现在&#34;功能&#34;字。我需要让TypeScript编译器通过,但我不知道如何。

2 个答案:

答案 0 :(得分:3)

虽然使用<any>将摆脱编译器投诉,但您基本上是回避强类型检查,这可以说是首先使用Typescript的要点之一。我很长一段时间都在努力解决这个问题,最后,通过试验和错误以及the d3.d.ts definition for d3.svg.arc的大量质量时间,能够找到一种方法来使所有类型排成一行。这是一个演示如何在不使用<any>的情况下获取饼图的解决方案。关键是您需要指定一个描述输入形状的interface,即您的数据:

interface Datum {
    category: string;
    quantity: number;
}

function drawChart(data: Array<Datum>) {

    let width = 960,
        height = 500,
        radius = Math.min(width, height) / 2,
        colourValues = d3.scale.category10();

    // specify Datum as shape of data
    let arc = d3.svg.arc<d3.layout.pie.Arc<Datum>>()
        .innerRadius(radius - 70)
        .outerRadius(radius - 10);

    // notice accessor receives d of type Datum
    let pie = d3.layout.pie<Datum>().sort(null).value((d: Datum):number => d.quantity);

    // note input to all .attr() and .text() functions
    // will be of type d3.layout.pie.Arc<Datum>
    let fill = (d: d3.layout.pie.Arc<Datum>): string => colourValues(d.data.category);
    let tfx  = (d: d3.layout.pie.Arc<Datum>): string => `translate(${arc.centroid(d)})`;
    let text = (d: d3.layout.pie.Arc<Datum>): string => d.data.category;

    let svg = d3.select('.pie-chart').append('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

    // create a group for the pie chart
    let g = svg.selectAll('.arc')
        .data(pie(data))
        .enter().append('g').attr('class', 'arc');

    // add pie sections
    g.append('path').attr('d', arc).attr('fill', fill);

    // add labels
    g.append('text').attr('transform', tfx).text(text);
}

请注意,我将ColourService替换为标准d3颜色类别函数之一,但只要colourValues()返回指定填充颜色的字符串,它就应该仍然有效。

希望此示例显示如何使您的自定义数据类型与d3和Typescript一起使用。

答案 1 :(得分:2)

好吧我弄清楚发生了什么,虽然我不完全理解D3如何使用TypeScript。基本上有两种解决方案:

第一个,我在datum参数上设置特定接口并返回值(字符串,数字或布尔值),然后将返回值强制转换为字符串 - 它太罗嗦了。

in_same_meta

第二种解决方案在眼睛上更容易。我只在函数中添加了g.append('path') .attr('d', <any>arc) .attr('fill', function (datum: d3.layout.pie.Arc<any>): number | string | boolean { return <string>colourValues(datum.data.category); }); 作为返回类型。

:any

我仍然不完全理解如何连接我在D3中与之交互的数据模型 - 每次我尝试使用已经在成功的承诺解析中实现的接口通过g.append('path') .attr('d', <any>arc) .attr('fill', function (d: any): any { return colourValues(d.data.category); }); 包含在角度内的D3函数中指令的链接函数,我遇到TypeScript编译错误,必须使用angular.IPromise<interfaceNameOfTheReturnData>类型。