目前,React 的SyntheticEvent
的 Typescript 2.0 签名如下所示:
interface SyntheticEvent<T> {
currentTarget: EventTarget & T;
target: EventTarget;
}
根据提交 a13fa7abf55daedf25b31258b908548f55962c7a, target
最初是EventTarget & T
,但此更改(显然)在提交 5607f54defce88bc52a0f453422.c 的合并期间意外恢复
当前的签名破坏了很多 2.0 之前的代码(你可以想象,React 代码充满了事件处理程序),但几乎没有任何好处(因为大多数代码依赖于event.target
,所以这意味着仍然依赖于 pre -2.0 代码像(event.target as any).value
,因为event.target
不是通用的。
我很乐意提供补丁,但我想确保SyntheticEvent.target
不是故意去通用化的。
这可能是合并过程中犯的错误。 请做公关。
参见 #11041、#10784 等等。 为什么即使在合并后它也没有修复是一个谜。
你不能总是在编译时告诉目标的类型。 使它成为通用的价值不大。
target 是事件的起源(没有人真正关心它,例如它可能是链接内的一个跨度)
currentTarget 是附加了事件处理程序的元素,如果您将数据集或其他属性附加到它并打算在运行时访问,您应该非常关心并相应地键入。
依赖 target 而不是 currentTarget 是初学者的错误,它会比后者更快地咬住他们。
例如:
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>
}
此代码用于编译,因为它应该。
合并“修复”后, e.currentTarget
不可打字(如果没有类型错误,我无法访问其数据集)并且e.target
现在被输入为 HTMLLinkElement,而实际上没有办法我们可以肯定。 (我可能点击了里面的跨度。
从理论上讲,我们可以在 SyntheticEvent 中添加第二个泛型,以键入目标,当用户对其确定时(事件处理程序没有子项,或者它们都具有相同的类型)。 但它没有什么价值,而且确实具有误导性(因为它仅适用于使用强制转换会更有意义的特定情况)。
特别是,如果您没有孩子,则可以使用 currentTarget。
另外它是完全错误的,在DOMAttributes<SomeType>
,你得到一个onClick
: MouseEventHandler<SomeType>
,然后得到EventHandler<MouseEvent<SomeType>>
interface EventHandler<E extends SyntheticEvent<any>> {
(event: E): void;
}
您绝对不能键入与 currentTarget 不同的 target。 onClick 需要一个具有处理事件(又名 currentTarget)作为泛型的事件处理程序。 它不能是别的东西,它不会编译。
@bbenezech
handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => { ... }
我建议改为:
handleTabClick = (e: React.FormEvent<HTMLLinkElement>) => { ... }
您还有ClipboardEvent<T>
、 CompositionEvent<T>
、 DragEvent<T>
、 FocusEvent<T>
、 KeyboardEvent<T>
...
SyntheticEvent 是低级的东西。
在@types NPM 存储库中仍然是这样。 关于何时发布的任何更新
这个改回来了。 见#12239。
最有用的评论
你不能总是在编译时告诉目标的类型。 使它成为通用的价值不大。
target 是事件的起源(没有人真正关心它,例如它可能是链接内的一个跨度)
currentTarget 是附加了事件处理程序的元素,如果您将数据集或其他属性附加到它并打算在运行时访问,您应该非常关心并相应地键入。
依赖 target 而不是 currentTarget 是初学者的错误,它会比后者更快地咬住他们。
例如:
此代码用于编译,因为它应该。
合并“修复”后,
e.currentTarget
不可打字(如果没有类型错误,我无法访问其数据集)并且e.target
现在被输入为 HTMLLinkElement,而实际上没有办法我们可以肯定。 (我可能点击了里面的跨度。从理论上讲,我们可以在 SyntheticEvent 中添加第二个泛型,以键入目标,当用户对其确定时(事件处理程序没有子项,或者它们都具有相同的类型)。 但它没有什么价值,而且确实具有误导性(因为它仅适用于使用强制转换会更有意义的特定情况)。
特别是,如果您没有孩子,则可以使用 currentTarget。