Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type 'string' is not assignable to type 'number' when creating color scale using d3.scaleQuantile

I am trying to replicate this d3 heatmap in a React application (with TypeScript). However, the following code gives me the headache:

 const colorScale = d3.scaleQuantile()
     .domain([0, buckets - 1, d3.max(data, (d: any) => parseInt(d.value))])
     .range(colors);

colors is underlined with red, indicating the following error:

Type 'string' is not assignable to type 'number'

I wonder how I can mitigate this issue.

like image 588
renakre Avatar asked Oct 21 '19 20:10

renakre


1 Answers

There are minor differences to the answer depending on the version of the scale module in use. The main solution, whatsoever, is not affected by that and applicable to all versions.

D3 v4 bundled

The example you linked to uses D3 v4 which depends on the d3-scale module v1.

If you look at the type definitions for d3.scaleQuantile() you will notice there are two definitions for its creation:

/**
 * Constructs a new quantile scale with an empty domain and an empty range.
 * The quantile scale is invalid until both a domain and range are specified.
 */
export function scaleQuantile(): ScaleQuantile<number>;

/**
 * Constructs a new quantile scale with an empty domain and an empty range.
 * The quantile scale is invalid until both a domain and range are specified.
 *
 * The generic corresponds to the data type of range elements.
 */
export function scaleQuantile<Range>(): ScaleQuantile<Range>;

Because you did not specify the generic Range type parameter the compiler defaults to the first definition inferring the type of your range to be a number and, hence, the error for your range containing strings.

This can easily be solved, though, by explicitly specifying the type of the scale's range, namely, string:

 const colorScale = d3.scaleQuantile<string>()  // Specify the type of the scale's range: <string>.
     .domain([0, buckets - 1, d3.max(data, (d: any) => parseInt(d.value))])
     .range(colors);

D3 v5 bundled

D3 v5 uses version 2 of the d3-scale module with only minor changes to the scale's type definitions.

d3-scale standalone

Be careful when using the type definition for d3-scale for the standalone module as they where created for the module's version 2.1.2. At the time of writing the latest standalone version is 3.1.0 which contains significant changes to the API! Alas, there are no type definitions available for that version.

like image 153
altocumulus Avatar answered Sep 25 '22 23:09

altocumulus