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


