Definitelytyped: Jadikan React.SyntheticEvent.target generik di atas T, bukan React.SyntheticEvent.currentTarget

Dibuat pada 26 Sep 2016  ·  7Komentar  ·  Sumber: DefinitelyTyped/DefinitelyTyped

Saat ini, tanda tangan TypeScript 2.0 untuk SyntheticEvent React terlihat seperti:

interface SyntheticEvent<T> {
    currentTarget: EventTarget & T;
    target: EventTarget;
}

Menurut commit a13fa7abf55daedf25b31258b908548f55962c7a, target awalnya EventTarget & T , tetapi perubahan ini (tampaknya) secara tidak sengaja dikembalikan selama penggabungan di commit 5607f54defce88bc52a0440288f434cafffdb5ce.

Tanda tangan saat ini merusak banyak kode pra-2.0 (seperti yang dapat Anda bayangkan, kode React penuh dengan event handler) dengan sedikit atau tanpa manfaat (karena sebagian besar kode bergantung pada event.target , jadi ini berarti masih mengandalkan pra -2.0 kode seperti (event.target as any).value , karena event.target tidak generik.

Saya akan dengan senang hati memberikan tambalan, tetapi saya ingin memastikan bahwa SyntheticEvent.target tidak sengaja di-degenerasi.

Komentar yang paling membantu

Anda tidak dapat selalu memberi tahu tipe target pada waktu kompilasi. Membuatnya generik adalah nilai kecil.
target adalah asal acara (yang tidak dipedulikan oleh siapa pun, mungkin rentang di dalam tautan, misalnya)
currentTarget adalah elemen yang memiliki event handler yang dilampirkan, yang harus Anda perhatikan dan ketik sesuai dengan itu jika Anda melampirkan kumpulan data atau atribut lain ke dalamnya, dan berniat untuk mengakses saat runtime.

Mengandalkan target alih-alih Target saat ini adalah kesalahan pemula yang akan menggigit mereka lebih cepat daripada yang terakhir.

Sebagai contoh:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

Kode ini digunakan untuk mengkompilasi, sebagaimana mestinya.

Dengan penggabungan 'perbaikan', e.currentTarget tidak dapat diketik (saya tidak dapat mengakses kumpulan datanya tanpa kesalahan ketik) dan e.target sekarang diketik sebagai HTMLLinkElement, padahal sebenarnya tidak ada cara kita bisa yakin tentang itu. (Saya mungkin telah mengklik rentang di dalamnya.

Secara teoritis kita bisa menambahkan generik kedua ke SyntheticEvent, untuk mengetik target, ketika pengguna yakin tentang hal itu (tidak ada anak-anak ke event handler, atau mereka semua memiliki tipe yang sama). Tetapi nilainya kecil dan benar-benar menyesatkan (karena itu hanya berlaku untuk kasus-kasus tertentu di mana menggunakan casting akan jauh lebih masuk akal).
Secara khusus, jika Anda tidak memiliki anak, Anda dapat menggunakan currentTarget.

Semua 7 komentar

Ini mungkin kesalahan yang dibuat selama penggabungan. Tolong buatkan PRnya.

lihat #11041, #10784 dan banyak lagi. Adalah misteri mengapa itu tidak diperbaiki bahkan setelah digabungkan.

Anda tidak dapat selalu memberi tahu tipe target pada waktu kompilasi. Membuatnya generik adalah nilai kecil.
target adalah asal acara (yang tidak dipedulikan oleh siapa pun, mungkin rentang di dalam tautan, misalnya)
currentTarget adalah elemen yang memiliki event handler yang dilampirkan, yang harus Anda perhatikan dan ketik sesuai dengan itu jika Anda melampirkan kumpulan data atau atribut lain ke dalamnya, dan berniat untuk mengakses saat runtime.

Mengandalkan target alih-alih Target saat ini adalah kesalahan pemula yang akan menggigit mereka lebih cepat daripada yang terakhir.

Sebagai contoh:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

Kode ini digunakan untuk mengkompilasi, sebagaimana mestinya.

Dengan penggabungan 'perbaikan', e.currentTarget tidak dapat diketik (saya tidak dapat mengakses kumpulan datanya tanpa kesalahan ketik) dan e.target sekarang diketik sebagai HTMLLinkElement, padahal sebenarnya tidak ada cara kita bisa yakin tentang itu. (Saya mungkin telah mengklik rentang di dalamnya.

Secara teoritis kita bisa menambahkan generik kedua ke SyntheticEvent, untuk mengetik target, ketika pengguna yakin tentang hal itu (tidak ada anak-anak ke event handler, atau mereka semua memiliki tipe yang sama). Tetapi nilainya kecil dan benar-benar menyesatkan (karena itu hanya berlaku untuk kasus-kasus tertentu di mana menggunakan casting akan jauh lebih masuk akal).
Secara khusus, jika Anda tidak memiliki anak, Anda dapat menggunakan currentTarget.

Plus itu sepenuhnya salah, pada DOMAttributes<SomeType> , Anda mendapatkan onClick : MouseEventHandler<SomeType> , lalu mendapatkan EventHandler<MouseEvent<SomeType>> dengan

    interface EventHandler<E extends SyntheticEvent<any>> {
        (event: E): void;
    }

Anda benar-benar tidak dapat mengetik target secara berbeda dari currentTarget. onClick mengharapkan event handler yang menangani event (alias currentTarget) sebagai generik. Itu tidak bisa menjadi sesuatu yang lain, itu tidak akan dikompilasi.

@bbenezech

handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => { ... }

Saya menyarankan sebagai gantinya:

handleTabClick = (e: React.FormEvent<HTMLLinkElement>) => { ... }

Anda juga memiliki ClipboardEvent<T> , CompositionEvent<T> , DragEvent<T> , FocusEvent<T> , KeyboardEvent<T> ...
SyntheticEvent adalah hal tingkat rendah.

Ini masih seperti ini di repositori @types NPM. Setiap pembaruan tentang kapan ini akan diterbitkan

Ini diubah kembali. Lihat #12239.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat