SixtyEight
SixtyEight

Reputation: 2490

Overriding d3 TypeScript definition file

I've got the following variable declaration

const xScale = d3
      .scaleLinear()
      .range([0, width - margin])
      .domain(
        d3.extent(wave, function(d) {
          return d[0];
        })
      );

wave receives an array of an array of numbers such as

code sample

If I type the d argument as

//
        d3.extent(wave, function(d:number[][]) {
          return d[0];
        })
//

It will return this error

TS2769: No overload matches this call.   Overload 1 of 4, '(array: ArrayLike, accessor: (datum: number[][], index: number, array: ArrayLike) => string | null | undefined): [string, string] | [undefined, undefined]', gave the following error.     Argument of type '(d: number[][]) => number[]' is not assignable to parameter of type '(datum: number[][], index: number, array: ArrayLike) => string | null | undefined'.       Type 'number[]' is not assignable to type 'string'.   Overload 2 of 4, '(array: ArrayLike, accessor: (datum: number[][], index: number, array: ArrayLike) => Numeric | null | undefined): [undefined, undefined] | [Numeric, Numeric]', gave the following error.     Argument of type '(d: number[][]) => number[]' is not assignable to parameter of type '(datum: number[][], index: number, array: ArrayLike) => Numeric | null | undefined'.       Type 'number[]' is not assignable to type 'Numeric'.         Types of property 'valueOf' are incompatible.           Type '() => Object' is not assignable to type '() => number'.             Type 'Object' is not assignable to type 'number'.

If I don't type such as

//
        d3.extent(wave, function(d:number[][]) {
          return d[0];
        })
//

I'll get this error

TS2345: Argument of type '[string, string] | [undefined, undefined]' is not assignable to parameter of type '(number | { valueOf(): number; })[]'.   Type '[string, string]' is not assignable to type '(number | { valueOf(): number; })[]'.     Type 'string' is not assignable to type 'number | { valueOf(): number; }'.

Looking at the d3 definition file it expects something different that I'm not providing but it's working for me:

export function extent(array: ArrayLike): [string, string] | [undefined, undefined];

Any hints about how to overcome these errors and type it properly? Much appreciated.

Upvotes: 2

Views: 502

Answers (1)

euclio
euclio

Reputation: 1497

The second parameter of extent is an "accessor", which is the same parameter that array.map takes. The current typings for d3 are too strict: they require (datum: T, index: number) as the accessor parameter type, but index is optional.

To get your current code to type-check, change function(d) to be function(d, i), even though i is unused.

A more correct solution would be to fork the definitely-typed repository and make the index parameter optional in the typings by adding ? to the end of the parameter name. As an example, for one overload:

export function extent<T>(array: T[], accessor: (datum: T, index?: number) => number): [number, number];

You can then use the typings from your fork and submit a patch upstream, which is explained in detail in this answer.

Upvotes: 1

Related Questions