Definitelytyped: React.SyntheticEvent.currentTargetではなく、React.SyntheticEvent.targetをT上でジェネリックにします

作成日 2016年09月26日  ·  7コメント  ·  ソース: DefinitelyTyped/DefinitelyTyped

現在、ReactのSyntheticEvent Typescript2.0署名は次のようになっています。

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

コミットa13fa7abf55daedf25b31258b908548f55962c7aによると、 targetは元々 EventTarget & Tが、この変更は(明らかに)コミット5607f54defce88bc52a0440288f434cafffdb5ceのマージ中に誤って元に戻されました。

現在の署名は、2.0より前のコードの多くを壊します(ご想像のとおり、Reactコードにはイベントハンドラーがたくさんあります)。ほとんどのコードはevent.targetに依存しているため、これはまだpreに依存していることを意味します。 (event.target as any).value event.targetは汎用ではないため、 (event.target as any).valueような2.0コード。

パッチを提供させていただきますが、 SyntheticEvent.targetが意図的に縮退されていないことを確認したいと思います。

最も参考になるコメント

コンパイル時にターゲットのタイプが常にわかるとは限りません。 それを一般的にすることはほとんど価値がありません。
ターゲットはイベントの発生源です(これは誰も気にしません。たとえば、リンク内のスパンである可能性があります)
currentTargetは、イベントハンドラーがアタッチされている要素です。データセットやその他の属性をアタッチし、実行時にアクセスする場合は、それに応じて注意して入力する必要があります。

currentTargetの代わりにtargetに依存することは、初心者の間違いであり、後者よりも早く彼らを噛みます。

例えば:

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

このコードは、必要に応じてコンパイルするために使用されていました。

'fix'がマージされると、 e.currentTargetは入力できなくなり(入力エラーがないとデータセットにアクセスできません)、 e.targetはHTMLLinkElementとして入力されるようになりましたが、実際には方法がありません。私たちはそれについて確信することができます。 (内側のスパンをクリックした可能性があります。

理論的には、ユーザーがそれについて確信している場合(イベントのハンドラーに子がないか、すべて同じタイプである場合)、SyntheticEventに2番目のジェネリックを追加してターゲットを入力できます。 しかし、それはほとんど価値がなく、本当に誤解を招く可能性があります(キャストを使用する方がはるかに理にかなっている特定の場合にのみ適用されるため)。
特に、子がない場合は、currentTargetを使用できます。

全てのコメント7件

これはおそらく、マージ中に行われた間違いです。 PRしてください。

#11041、#10784などを参照してください。 マージ後も修正されないのは謎です。

コンパイル時にターゲットのタイプが常にわかるとは限りません。 それを一般的にすることはほとんど価値がありません。
ターゲットはイベントの発生源です(これは誰も気にしません。たとえば、リンク内のスパンである可能性があります)
currentTargetは、イベントハンドラーがアタッチされている要素です。データセットやその他の属性をアタッチし、実行時にアクセスする場合は、それに応じて注意して入力する必要があります。

currentTargetの代わりにtargetに依存することは、初心者の間違いであり、後者よりも早く彼らを噛みます。

例えば:

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

このコードは、必要に応じてコンパイルするために使用されていました。

'fix'がマージされると、 e.currentTargetは入力できなくなり(入力エラーがないとデータセットにアクセスできません)、 e.targetはHTMLLinkElementとして入力されるようになりましたが、実際には方法がありません。私たちはそれについて確信することができます。 (内側のスパンをクリックした可能性があります。

理論的には、ユーザーがそれについて確信している場合(イベントのハンドラーに子がないか、すべて同じタイプである場合)、SyntheticEventに2番目のジェネリックを追加してターゲットを入力できます。 しかし、それはほとんど価値がなく、本当に誤解を招く可能性があります(キャストを使用する方がはるかに理にかなっている特定の場合にのみ適用されるため)。
特に、子がない場合は、currentTargetを使用できます。

さらに、それは完全に間違っています。 DOMAttributes<SomeType>で、 onClickMouseEventHandler<SomeType>を取得し、次にEventHandler<MouseEvent<SomeType>>を取得します。

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

currentTargetとは異なる方法でターゲットを入力することは絶対にできません。 onClickは、ジェネリックとして処理イベント(別名currentTarget)を持つイベントハンドラーを想定しています。 それは他のものになることはできません、それはコンパイルされません。

@bbenezech

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

代わりに提案します:

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

ClipboardEvent<T>CompositionEvent<T>DragEvent<T>FocusEvent<T>KeyboardEvent<T> ..もあります。
SyntheticEventは低レベルのものです。

これは、 @ typesNPMリポジトリではまだこのようになっています。 これがいつ公開されるかに関する更新

これは元に戻されました。 #12239を参照してください。

このページは役に立ちましたか?
0 / 5 - 0 評価