Typescriptの要素ではなくEvent.targetがあるのはなぜですか?


115

これを自分のKeyboardEventで実行したいだけです

var tag = evt.target.tagName.toLowerCase();

Event.targetはEventTargetタイプですが、Elementから継承しません。だから私はこのようにキャストする必要があります:

var tag = (<Element>evt.target).tagName.toLowerCase();

これはおそらく、一部のブラウザが標準に従っていないためです。TypeScriptでのブラウザに依存しない正しい実装は何ですか?

PS:私は、jQueryを使用してKeyboardEventをキャプチャしています。


7
少しvar element = ev.target as HTMLElement
すっきりした

回答:


57

Elementすべてのイベントターゲットが要素であるわけではないため、継承しません。

MDNから

要素、ドキュメント、ウィンドウは最も一般的なイベントターゲットですが、XMLHttpRequest、AudioNode、AudioContextなどの他のオブジェクトもイベントターゲットにすることができます。

KeyboardEvent使用しようとしているものでも、DOM要素またはウィンドウオブジェクト(および理論的には他のもの)で発生する可能性があるためevt.target、として定義しても意味がありませんElement

それがDOM要素のイベントである場合、私はあなたが安全に仮定できると言いますevt.target。ですElement。これはブラウザ間の動作の問題ではないと思います。単にそれEventTargetよりも抽象的なインターフェースですElement

さらに読む:https : //typescript.codeplex.com/discussions/432211


8
その場合、KeyboardEventとMouseEventには、関連付けられたElementを常に含むEventTargetと同等の独自のイベントが必要です。DOMはとても危険です...:/
daniel.sedlacek

7
私はDOMやTypeScriptの専門家ではありませんが、EventTargetの設計にはあいまいさが多すぎて、TypeScriptとは何の関係もありません。
daniel.sedlacek 2015年

2
@ daniel.sedlacek一方、KeyboardEventSはそうすぐそこにそれが与えることは不可能だ、両方のDOM要素に、ウィンドウオブジェクト(および理論的には他のもの)で発生する可能性がありますKeyboardEvent.targetよりも、それ以上の特定の型をEventTargetあなたが考えていない限り、KeyboardEventまた、Aでなければなりませんジェネリック型でKeyboardEvent<T extends EventTarget>ありKeyboardEvent<Element>、コード全体に強制的に配置する必要があります。その時点で、明示的なキャストを行うだけの方がベターですが、痛みを伴う場合もあります。
JLRishe 2015年

14
将来的に他の人にとっても役立つ場合valueは、<select>タグのプロパティにアクセスするために、特定の要素タイプとしてキャストする必要がありました。例let target = <HTMLSelectElement> evt.target;
munsellj

1
@munsellj(残念ながら)これは、型付き環境であいまいさを処理する正しい方法です。
pilau

47

typescriptを使用して、自分の関数にのみ適用されるカスタムインターフェイスを使用します。使用例。

  handleChange(event: { target: HTMLInputElement; }) {
    this.setState({ value: event.target.value });
  }

この場合、handleChangeは、HTMLInputElementタイプのターゲットフィールドを持つオブジェクトを受け取ります。

後でコードで使用できます

<input type='text' value={this.state.value} onChange={this.handleChange} />

より明確なアプローチは、インターフェースを別のファイルに置くことです。

interface HandleNameChangeInterface {
  target: HTMLInputElement;
}

その後、次の関数定義を使用します。

  handleChange(event: HandleNameChangeInterface) {
    this.setState({ value: event.target.value });
  }

私のユースケースでは、handleChangeの唯一の呼び出し元は、入力テキストのHTML要素タイプであることが明確に定義されています。


これは私にとって完璧に機能しました-あらゆる種類の厄介な試み、EventTargetの拡張などを試みていましたが、これは最もクリーンなソリューションです+1
Kitson

1
:ちょうどあなたがイベント定義を拡張する必要がある場合は、このような何か行うことができ、これに追加するhandleKeyUp = (event: React.KeyboardEvent<HTMLInputElement> & { target: HTMLInputElement }) => {...}
キットソン


28

Typescript 3.2.4

プロパティを取得するには、ターゲットを適切なデータ型にキャストする必要があります。

e => console.log((e.target as Element).id)

それは<HTMLInputElement>event.target;構文と同じですか?
Konrad Viltersten

@KonradViltersten、彼らは同じことをします。asそれはJSXと競合するので、構文が導入されました。as一貫性を保つために使用することをお勧めします。basarat.gitbooks.io/typescript/docs/types/type-assertion.html
Adam

ああ、なるほど。また、チームのバックエンドエクスペリエンスに応じて、多くの場合に利点となるC#っぽさが増しています。構文が何かに似ているが、技術的にはまったく異なる何かを意味するのは、これらの誤った友達ではない限り。(AngularとC#の間のvarconstを考えています。私の悲しい経験です)。
Konrad Viltersten

2

あなたは拡張し、独自の汎用インタフェースを作成することができますEvent。このようなもの?

interface DOMEvent<T extends EventTarget> extends Event {
  target: T
}

その後、次のように使用できます。

handleChange(event: DOMEvent<HTMLInputElement>) {
  this.setState({ value: event.target.value });
}

1

typescriptを使用すると、次のように型エイリアスを利用できます。

type KeyboardEvent = {
  target: HTMLInputElement,
  key: string,
};
const onKeyPress = (e: KeyboardEvent) => {
  if ('Enter' === e.key) { // Enter keyboard was pressed!
    submit(e.target.value);
    e.target.value = '';
    return;
  }
  // continue handle onKeyPress input events...
};

0

@Bangonkaliは正しい答えを提供しますが、この構文はより読みやすく、ちょうど良いように見えます:

eventChange($event: KeyboardEvent): void {
    (<HTMLInputElement>$event.target).value;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.