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
2 Answers
Reset to default 4As 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>) {
...
}