Definitelytyped: Machen Sie React.SyntheticEvent.target generisch über T, nicht React.SyntheticEvent.currentTarget

Erstellt am 26. Sept. 2016  ·  7Kommentare  ·  Quelle: DefinitelyTyped/DefinitelyTyped

Derzeit sieht die Typescript 2.0-Signatur für SyntheticEvent React so aus:

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

Laut Commit a13fa7abf55daedf25b31258b908548f55962c7a war target ursprünglich EventTarget & T , aber diese Änderung wurde (anscheinend) versehentlich während einer Zusammenführung in Commit 5607f54defce88bc52a0440288f434cafffdb5ce rückgängig gemacht.

Die aktuelle Signatur bricht eine Menge Code vor 2.0 (wie Sie sich vorstellen können, ist React-Code voller Event-Handler) für wenig bis gar keinen Nutzen (da der meiste Code auf event.target basiert, bedeutet dies also, dass man sich immer noch auf pre verlässt -2.0 Code wie (event.target as any).value , da event.target nicht generisch ist.

Ich werde gerne einen Patch bereitstellen, aber ich möchte sicher sein, dass SyntheticEvent.target nicht absichtlich degeneriert wurde.

Hilfreichster Kommentar

Sie können den Typ des Ziels zur Kompilierzeit nicht immer angeben. Es ist von geringem Wert, es generisch zu machen.
target ist der Ursprung des Ereignisses (was niemanden wirklich interessiert, es könnte zum Beispiel ein Span innerhalb eines Links sein)
currentTarget ist das Element, an das der Event-Handler angehängt ist, das Sie sehr beachten und entsprechend eingeben sollten, wenn Sie ein Dataset oder andere Attribute daran angehängt haben und zur Laufzeit darauf zugreifen möchten.

Sich auf target statt auf currentTarget zu verlassen, ist ein Anfängerfehler, der sie eher beißt als letztere.

Zum Beispiel:

  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>
}

Dieser Code wurde zum Kompilieren verwendet, wie er sollte.

Mit dem zusammengeführten 'Fix' ist e.currentTarget nicht typisierbar (ich kann ohne einen Typfehler nicht auf seinen Datensatz zugreifen) und e.target wird jetzt als HTMLLinkElement eingegeben, obwohl dies tatsächlich nicht möglich ist da können wir uns sicher sein. (Vielleicht habe ich die Spanne innen angeklickt.

Theoretisch könnten wir SyntheticEvent einen zweiten generischen Typ hinzufügen, um target zu typisieren, wenn der Benutzer sich darüber sicher ist (keine Kinder zum Handler des Ereignisses oder sie haben alle den gleichen Typ). Aber es ist von geringem Wert und wirklich irreführend (weil es nur für bestimmte Fälle gilt, in denen die Verwendung von Casting viel sinnvoller wäre).
Insbesondere wenn Sie keine Kinder haben, können Sie currentTarget verwenden.

Alle 7 Kommentare

Dies ist wahrscheinlich ein Fehler, der beim Zusammenführen gemacht wurde. Bitte mach eine PR.

siehe #11041, #10784 und viele mehr. Ist ein Rätsel, warum es auch nach dem Zusammenführen nicht behoben wird.

Sie können den Typ des Ziels zur Kompilierzeit nicht immer angeben. Es ist von geringem Wert, es generisch zu machen.
target ist der Ursprung des Ereignisses (was niemanden wirklich interessiert, es könnte zum Beispiel ein Span innerhalb eines Links sein)
currentTarget ist das Element, an das der Event-Handler angehängt ist, das Sie sehr beachten und entsprechend eingeben sollten, wenn Sie ein Dataset oder andere Attribute daran angehängt haben und zur Laufzeit darauf zugreifen möchten.

Sich auf target statt auf currentTarget zu verlassen, ist ein Anfängerfehler, der sie eher beißt als letztere.

Zum Beispiel:

  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>
}

Dieser Code wurde zum Kompilieren verwendet, wie er sollte.

Mit dem zusammengeführten 'Fix' ist e.currentTarget nicht typisierbar (ich kann ohne einen Typfehler nicht auf seinen Datensatz zugreifen) und e.target wird jetzt als HTMLLinkElement eingegeben, obwohl dies tatsächlich nicht möglich ist da können wir uns sicher sein. (Vielleicht habe ich die Spanne innen angeklickt.

Theoretisch könnten wir SyntheticEvent einen zweiten generischen Typ hinzufügen, um target zu typisieren, wenn der Benutzer sich darüber sicher ist (keine Kinder zum Handler des Ereignisses oder sie haben alle den gleichen Typ). Aber es ist von geringem Wert und wirklich irreführend (weil es nur für bestimmte Fälle gilt, in denen die Verwendung von Casting viel sinnvoller wäre).
Insbesondere wenn Sie keine Kinder haben, können Sie currentTarget verwenden.

Außerdem ist es völlig falsch, bei einem DOMAttributes<SomeType> bekommst du ein onClick : MouseEventHandler<SomeType> , dann bekommst du EventHandler<MouseEvent<SomeType>> mit

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

Sie können target absolut nicht anders als currentTarget eingeben. onClick erwartet einen Ereignishandler, der als Generikum ein Ereignisbehandlungsereignis (auch bekannt als currentTarget) hat. Es kann nichts anderes sein, es wird nicht kompiliert.

@bbenezech

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

Ich schlage stattdessen vor:

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

Sie haben auch ClipboardEvent<T> , CompositionEvent<T> , DragEvent<T> , FocusEvent<T> , KeyboardEvent<T> ...
SyntheticEvent ist das Low-Level-Ding.

Dies ist im @types NPM-Repository immer noch so. Jedes Update, wann dies veröffentlicht wird

Dies wurde wieder geändert. Siehe #12239.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen