Typescript + React + D3v4: `Object is possibly 'undefined' error`, at d3 scaleBand

Viewed 573

How to resolve the Object is possibly 'undefined' error, that occurs at 'yScale'

interface IData {
  id: string;
  phone_number: string,
}
const data : IData[]
const devices = data.map((d) => d.phone_number)
const yScale = d3.scaleBand()
  .range([0, 30 * devices.length])
  .domain(devices)

const yAccessor = (d: string) => yScale(d)

I think it is occurring because typescript thinks d3's scaleBand will return undefined because 'devices' variable is any empty array. When i hover over 'devices' in my IDE, it says 'let devices: string[]'. However, 'devices' in its initial state is empty (because a search has not been submitted). This error would not occur if 'devices' already contains a list of elements.

Here is d3-scale's type definitions

export interface ScaleBand<Domain extends { toString(): string }> {
    /**
     * Given a value in the input domain, returns the start of the corresponding band derived from the output range.
     * If the given value is not in the scale’s domain, returns undefined.
     *
     * @param x  A value from the domain.
     */
    (x: Domain): number | undefined;
...
}
2 Answers

One possible solution is to allow undefined/null values in the typescript compiler settings like in tsconfig. However I'm not sure whether that is recommended or not.

Given that the data could be an empty array, you could do a check before yScale is called to ensure that data is not empty.

if (!data.length) {
  return;
}
const devices = data.map((d) => d.phone_number)
const yScale = d3.scaleBand()
  .range([0, 30 * devices.length])
  .domain(devices)

This will cause an early return within your hook/method if data is an empty array.

Related