Atualmente, a assinatura do Typescript 2.0 para SyntheticEvent
do React se parece com:
interface SyntheticEvent<T> {
currentTarget: EventTarget & T;
target: EventTarget;
}
De acordo com o commit a13fa7abf55daedf25b31258b908548f55962c7a, target
era originalmente EventTarget & T
, mas esta alteração foi (aparentemente) acidentalmente revertida durante uma fusão no commit 5607f54defce88bc52a0440288f434cafffdb5ce.
A assinatura atual quebra muitos códigos pré-2.0 (como você pode imaginar, o código React está repleto de manipuladores de eventos) com pouco ou nenhum benefício (já que a maioria do código depende de event.target
, então isso significa ainda depender de pré -2.0 código como (event.target as any).value
, uma vez que event.target
não é genérico.
Ficarei feliz em fornecer um patch, mas gostaria de ter certeza de que SyntheticEvent.target
não foi desgenerificado de propósito.
Este é provavelmente um erro cometido durante a fusão. Por favor, faça um PR.
consulte # 11041, # 10784 e muitos mais. É um mistério o porquê de não ser corrigido mesmo após a fusão.
Você nem sempre pode dizer o tipo de destino em tempo de compilação. Torná-lo genérico tem pouco valor.
target é a origem do evento (com o qual ninguém realmente se preocupa, pode ser um intervalo dentro de um link, por exemplo)
currentTarget é o elemento que possui o manipulador de eventos anexado, com o qual você deve se preocupar muito e digitar de acordo se anexou um conjunto de dados ou outros atributos a ele e pretende acessar em tempo de execução.
Depender do alvo em vez de currentTarget é um erro do iniciante que irá mordê-los mais cedo do que tarde.
Por exemplo:
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>
}
Este código é usado para compilar, como deveria.
Com a 'correção' mesclada, e.currentTarget
não é digitável (não consigo acessar seu conjunto de dados sem um erro de tipo) e e.target
agora é digitado como um HTMLLinkElement, quando na verdade não há como podemos ter certeza sobre isso. (Posso ter clicado na extensão interna.
Teoricamente, poderíamos adicionar um segundo genérico a SyntheticEvent, para digitar target, quando o usuário tiver certeza disso (nenhum filho para o tratador de evento, ou todos têm o mesmo tipo). Mas é de pouco valor e realmente enganoso (porque se aplica apenas a casos específicos em que o uso de fundição faria muito mais sentido).
Em particular, se você não tem filhos, pode usar currentTarget.
Além disso, está completamente errado, em um DOMAttributes<SomeType>
, você obtém um onClick
: MouseEventHandler<SomeType>
, em seguida, obtém EventHandler<MouseEvent<SomeType>>
com
interface EventHandler<E extends SyntheticEvent<any>> {
(event: E): void;
}
Você absolutamente não pode digitar target diferente de currentTarget. onClick espera um manipulador de eventos que possui o evento de manipulação (também conhecido como currentTarget) como o genérico. Não pode ser outra coisa, não compilará.
@bbenezech
handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => { ... }
Em vez disso, sugiro:
handleTabClick = (e: React.FormEvent<HTMLLinkElement>) => { ... }
Você também tem ClipboardEvent<T>
, CompositionEvent<T>
, DragEvent<T>
, FocusEvent<T>
, KeyboardEvent<T>
...
SyntheticEvent é a coisa de baixo nível.
Isso ainda é assim no repositório do NPM @types . Qualquer atualização sobre quando isso será publicado
Isso foi mudado de volta. Veja # 12239.
Comentários muito úteis
Você nem sempre pode dizer o tipo de destino em tempo de compilação. Torná-lo genérico tem pouco valor.
target é a origem do evento (com o qual ninguém realmente se preocupa, pode ser um intervalo dentro de um link, por exemplo)
currentTarget é o elemento que possui o manipulador de eventos anexado, com o qual você deve se preocupar muito e digitar de acordo se anexou um conjunto de dados ou outros atributos a ele e pretende acessar em tempo de execução.
Depender do alvo em vez de currentTarget é um erro do iniciante que irá mordê-los mais cedo do que tarde.
Por exemplo:
Este código é usado para compilar, como deveria.
Com a 'correção' mesclada,
e.currentTarget
não é digitável (não consigo acessar seu conjunto de dados sem um erro de tipo) ee.target
agora é digitado como um HTMLLinkElement, quando na verdade não há como podemos ter certeza sobre isso. (Posso ter clicado na extensão interna.Teoricamente, poderíamos adicionar um segundo genérico a SyntheticEvent, para digitar target, quando o usuário tiver certeza disso (nenhum filho para o tratador de evento, ou todos têm o mesmo tipo). Mas é de pouco valor e realmente enganoso (porque se aplica apenas a casos específicos em que o uso de fundição faria muito mais sentido).
Em particular, se você não tem filhos, pode usar currentTarget.