typescript - D3-tapahtuma: Tyyppimääritykset versiosta 6 lähtien


Minulla on joukko widgettejä, jotka on kehitetty d3:lla (versio 5) ja nyt minun täytyy siirtää ne versioon 7. Muutto-ohjeessa https://observablehq.com/@d3/d3v6-migration-guide olen oppinut uuden syntaksin tapahtumille:

// before
element.on('click', (d, i, e) => ...


// now
element.on('click', (event, d) => ...

Kun vaihdoin uuteen syntaksiin, ohjelma alkoi taas toimia. Jee!

Ongelma nyt on se, että käytän TypeScriptiä tässä projektissa! Ja vaikka olen asentanut uusimmat @types/...

  "dependencies": {
      "d3": "^7.1.1",
         ...

  "devDependencies": {
      "@types/d3": "^7.1.0",
         ...

...Minulla on jatkuvasti ongelmia tyyppimääritelmien ja Intellisensen kanssa, kun on kyse tapahtumista.

// 1. before (Worked fine)
element.on('click', (d: MyData, i: number, e: whatever[]) => ...


// 2. introducing types == Error back! ❌  
element.on('click', (event: PointerEvent, d: MyData) => ...


// 3. then, my (ugly) workaround:
element.on('click', (event: any , d: any) => ...

Hauskaa on se, että vaikka minulla on asennettuna @types/d3 v7.0.1, Typings-järjestelmä näyttää silti pitävän viitteen vanhaan v5-muotoon. Jollain tavalla Intellisense ajattelee edelleen, että ensimmäinen parametrini on data ja toinen on numeerinen indeksi:

...Mutta tosielämässä saan sen muotoisena { event: PointerEvent, d: MyData }, kuten alla olevassa kuvassa on esitetty.

Joten, yksinkertaisesti sanottuna, tuntuu siltä, että D3:n tyyppimäärityksessä on ongelma, koska Intellisense ajattelee, että Event on edelleen v5-muodossa, vaikka todellisuudessa se ei ole.

Tiedätkö joku, miten tämä kirjoitusjuttu korjataan? On todella ärsyttävää joutua määrittämään "any" koko asialle tapahtumieni sisällä.

Vastaus #1

Kuten hyvin tiedät, on yleensä parasta välttää any kuin ruttoa, mikä on syy siihen, miksi yrität rajata sen tiettyyn tyyppiin! Tapahtumankuuntelijan tyypin määritelmän osalta olet kuitenkin epäonninen. Katsoessasi .on-metodin määritelmää huomaat, että event-parametri on tosiaan tyypitetty any-tyypiksi, mikä sallii kaikkein yleisimmän tapahtumankäsittelyn:

on(typenames: string, listener: (this: GElement, event: any, d: Datum) => void, options?: any): this;

Tästä syystä toinen lähestymistapasi epäonnistuu, jättäen kolmannen lähestymistavan ainoaksi oikeaksi ratkaisuksi.

Vastaus #2

Ratkaisin tämän lisäämällä koodipohjaani aputyypin D3Event, joka hyväksyy 2 tyyppiparametria:

export type D3Event<T extends Event, E extends Element> = T & { currentTarget: E }

Sitten voin käyttää sitä näin:

selection.on('mouseover', (event: D3Event<MouseEvent, SVGGElement>, d: SomeType) => { ... }

Se on hieman sanallisempi, mutta paljon tiukempi kuin any

Aiheeseen liittyviä artikkeleita