javascript - Typescriptin valinta, D3.js-funktion ylikuormitus ja palautustyyppi


Työskentelen tällä hetkellä d3.js:n, Reactin ja Typescriptin kanssa, ja minulla on vaikeuksia ymmärtää paras tapa määrittää funktioylikuormitus manuaalisesti ja poistaa mahdollisuus saada undefined-paluuarvo.

Alla olevassa esimerkissä yritän käyttää ulottuvuutta ja palauttaa [Date, Date] käyttämällä seuraavan tyyppistä pääsyfunktiota.

xAccessor: (datum: Window, index: number, array: Iterable<Window>) => Date

Esimerkkikäyttö:

const xScale = d3.scaleTime()
    .domain(d3.extent<Iterable<Window>, Iterable<Date>>(data, xAccessor))
    .range([0, dimensions.boundedWidth])

Ongelmana on, että saan tämän virheilmoituksen

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

Uskon, että tämä johtuu siitä, että DefinitelyTyped d3 -paketilla on seuraava määritelmä.

export function extent<T, U extends Numeric>(
    iterable: Iterable<T>,
    accessor: (datum: T, index: number, array: Iterable<T>) => U | undefined | null
): [U, U] | [undefined, undefined];

Huomaa, että Ikkuna-tyyppi ei salli määrittelemätöntä päivämäärää.

export interface Window {
    ts: Date;
    high: number;
    low: number;
    open: number;
    close: number;
    volume: number;
}

const dateAccessor = (d: Window) => d.ts

Olen nähnyt muita vastauksia kuten alla, joissa tarkistetaan määrittelemätön ja määritetään oletusarvo, mutta en ole varma, miten tehdä se ja silti hyödyntää propsien kautta lapseen komponenttiin välitettyä accessor-funktiota.

React, Typescript, d3js, Saadaan virhe 'No overload matches this call'

Onko olemassa oikeaa tapaa pakottaa tietty ylikuormitus ja samalla poistaa mahdollisuus määrittelemättömään tulokseen käytettäessä accessor-metodia, joka annetaan osana propsia?

Vastaus #1

Olen kohdannut samanlaisen ongelman samanlaisella koodilla, ja näin korjasin sen:

interface Entry {
  time: Date
}

x.domain(d3.extent(entries, (e: Entry): Date => e.time) as [Date, Date])

Tapauksessasi oletan, että jotain tämän tapaista pitäisi toimia:

const xScale = d3.scaleTime()
    .domain(d3.extent<Iterable<Window>, Iterable<Date>>(data, xAccessor) as [Date, Date])
    .range([0, dimensions.boundedWidth])