为什么Event.target不是Typescript中的元素?

dan*_*cek 87 typescript

我只想用我的KeyboardEvent来做这件事

var tag = evt.target.tagName.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

虽然Event.target的类型为EventTarget,但它不会从Element继承.所以我必须这样投:

var tag = (<Element>evt.target).tagName.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

这可能是因为有些浏览器没有遵循标准,对吧?TypeScript中与浏览器无关的正确实现是什么?

PS:我正在使用jQuery来捕获KeyboardEvent.

JLR*_*she 43

它不会继承,Element因为并非所有事件目标都是元素.

来自MDN:

元素,文档和窗口是最常见的事件目标,但其他对象也可以是事件目标,例如XMLHttpRequest,AudioNode,AudioContext等.

即使KeyboardEvent你正在尝试使用的东西也可能出现在DOM元素或窗口对象上(理论上也可能出现在其他东西上),所以就在那里evt.target定义为一个没有意义Element.

如果它是DOM元素上的事件,那么我会说你可以安全地假设evt.target.是一个Element.我不认为这是跨浏览器行为的问题.仅仅EventTarget是一个比抽象界面更抽象的界面Element.

进一步阅读:https://typescript.codeplex.com/discussions/432211

  • 如果它对将来的其他人有帮助,我需要转换为特定的元素类型,以便访问`<select>`标记的`value`属性.例如`let target = <HTMLSelectElement> evt.target;` (13认同)
  • 我不是DOM和TypeScript的专家,但我会说EventTarget的设计有太多歧义,而且与TypeScript无关. (5认同)
  • 在这种情况下,KeyboardEvent和MouseEvent应该拥有它自己的等效EventTarget,它将始终包含相关的Element.DOM是如此狡猾......:/ (3认同)
  • @ daniel.sedlacek另一方面,`KeyboardEvent`s可以同时在DOM元素和窗口对象上发生(以及从理论上讲是其他事情),因此,不可能给`KeyboardEvent.target`提供比它更具体的类型。 `EventTarget`,除非您认为`KeyboardEvent`也应该是通用类型`KeyboardEvent &lt;T扩展EventTarget&gt;`,并希望被迫在整个代码中全部放入`KeyboardEvent &lt;Element&gt;。那时,最好还是进行显式转换,尽管可能会很痛苦。 (2认同)
  • @munsellj(不幸的是)这是在类型化环境中处理歧义的正确方法。 (2认同)

Ban*_*ali 34

使用typescript,我使用仅适用于我的函数的自定义界面.用例示例.

  handleChange(event: { target: HTMLInputElement; }) {
    this.setState({ value: event.target.value });
  }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,handleChange将接收一个目标字段为HTMLInputElement类型的对象.

稍后在我的代码中我可以使用

<input type='text' value={this.state.value} onChange={this.handleChange} />
Run Code Online (Sandbox Code Playgroud)

更简洁的方法是将接口放在单独的文件中.

interface HandleNameChangeInterface {
  target: HTMLInputElement;
}
Run Code Online (Sandbox Code Playgroud)

然后使用以下函数定义:

  handleChange(event: HandleNameChangeInterface) {
    this.setState({ value: event.target.value });
  }
Run Code Online (Sandbox Code Playgroud)

在我的用例中,明确定义了handleChange的唯一调用者是HTML元素类型的输入文本.

  • 除此之外,如果您需要扩展事件定义,您可以执行以下操作:`handleKeyUp = (event: React.KeyboardEvent&lt;HTMLInputElement&gt; &amp; { target: HTMLInputElement }) =&gt; {...}` (3认同)

Sim*_*amp 22

JLRishe的答案是正确的,所以我只是在我的事件处理程序中使用它:

if (event.target instanceof Element) { /*...*/ }
Run Code Online (Sandbox Code Playgroud)

  • 这是最类型安全的解决方案! (6认同)

dim*_*iax 19

打字稿3.2.4

要检索属性,必须将target强制转换为适当的数据类型:

e => console.log((e.target as Element).id)
Run Code Online (Sandbox Code Playgroud)

  • 如果你不想让代码库中的骗子裤子着火,那么使用“as”应该是最后的手段。 (3认同)

Wic*_*ams 13

您能否创建自己的通用接口来扩展Event. 像这样的东西?

interface DOMEvent<T extends EventTarget> extends Event {
  readonly target: T
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

handleChange(event: DOMEvent<HTMLInputElement>) {
  this.setState({ value: event.target.value });
}
Run Code Online (Sandbox Code Playgroud)