Reputation: 43
In my Angular 5 project using D3 v5, if I give the following, the code will compile:
let y0 = d3.scaleLinear().domain([0, 100000]).range([this.height, 0]);
However, if I give the following with variable names for the upper and lower bounds of my domain, I get an error:
let y0 = d3.scaleLinear().domain([d3.min(data.totalCount), d3.max(data.totalCount)]).range([this.height, 0]);
Error: TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number | or ({valueOf(): number;})[]'. Type 'string' is not assignable to type 'number | or {valueOf(): number;}.
I know that the arguments going to d3.min and d3.max are numbers, and if I provide a test array of numbers, test = [1, 2, 3, 4]
, I get the same error.
Why is it trying to read these variables as strings? What am I doing wrong?
Upvotes: 3
Views: 1518
Reputation: 21578
There are actually four type definitions for d3.min()
:
export function min(array: ArrayLike<string>): string | undefined;
export function min<T extends Numeric>(array: ArrayLike<T>): T | undefined;
export function min<T>(array: ArrayLike<T>, accessor: (datum: T, index: number, array: ArrayLike<T>) => string | undefined | null): string | undefined;
export function min<T, U extends Numeric>(array: ArrayLike<T>, accessor: (datum: T, index: number, array: ArrayLike<T>) => U | undefined | null): U | undefined;
The compiler will choose the best fit for your code, which, given that you have not provided any type parameter, comes down to the first type definition. As you can see, this expects an ArrayLike<string>
argument and returns a string
or undefined
. This yields the error you observed. The same obviously holds true for d3.max()
.
Since you know your data.totalCount
are all numbers, you can easily pass that in as the type parameter for the generic function:
let y0 = d3.scaleLinear().domain([
d3.min<number>(data.totalCount),
d3.max<number>(data.totalCount)
]).range([this.height, 0]);
Side note not directly related to your problem: you can use d3.extent()
which combines d3.min()
and d3.max()
in a single call.
let y0 = d3.scaleLinear()
.domain(d3.extent<number>(data.totalCount))
.range([this.height, 0]);
Upvotes: 3