D3 axis and typescript

Dataviz logo representing a Lollipop chart.

What is typescript and why it is awesome to use it. How are d3 functions typed.

A few examples on how it works.

Useful links

Most basic linear axis

A graph axis is based on a scale. But what is a scale? This is how thed3-scale module describes it:

Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation

So basically a scale is a function. You provide it with an input like the value of a data point, and it returns another value like a position in pixel.

Here is a very basic implementation of a scale using the scaleLinear function of d3.

const xScale = d3.scaleLinear()
  .domain([0, 10]) // data can go from 0 to 10
  .range([0, width]); // it will result in a value that goes from 0 to width

// xScale(0) -> 0
// xScale(10) -> width
// xScale(5) -> width / 2

Scales are then used to build axis. Here is an example transforming the scale above in an X axis using a custom react component.

0246810

How to build a bottom axis and a left axis component using React, used to render a d3 scale.

Ok, now, how to deal with this in a typescript world?

scaleLinear and typescript

When we create a scale function using scaleLinear, it is equivalent as calling the function with the 3 default generics

// if you call
const xScale = d3.scaleLinear()

// it is equivalent to
const xScale = d3.scaleLinear<numeric, numeric, never>()

Here, the first generic is the type of the data items used for the range of scale. The second generic is the type of the data that the scale with output. You can see the explanations more in depth in the type definition of the scaleLinear function.

Now, what happens if we want to use scaleLinear to take a numeric value and map it to a color? In this case the range is gonna be an array of string. And the output is gonna be a color too. We can type it as:

// typing a color scale
const colorScale = d3.scaleLinear<string, string, never>()
  .range(['blue', 'green'])
  .domain([1, 100]);

scaleOrdinal and typescript

Consider a finite number of groups. We need to assign a specific color to each group. This is called an ordinal scale and is implemented in the d3 scaleOrdinal function.

What's needed here is thus a list of colors to use (the range) and a list of group names: the domain.

To put it in a nutshell, that's how the color scale is implemented:

// List of arbitrary colors
const COLORS = ["#e0ac2b", "#e85252", "#6689c6", "#9a6fb0", "#a53253"];

// List of all group names
const allGroups = data.map((group) => group.group);

// Color scale
const colorScale = d3.scaleOrdinal<string>()
  .domain(allGroups)
  .range(COLORS);

You can see how scaleOrdinal type implementation

General Knowledge

Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!