Definitelytyped: Hacer React.SyntheticEvent.target genérico sobre T, no React.SyntheticEvent.currentTarget

Creado en 26 sept. 2016  ·  7Comentarios  ·  Fuente: DefinitelyTyped/DefinitelyTyped

Actualmente, la firma Typecript 2.0 para SyntheticEvent de React se ve así:

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

De acuerdo con la confirmación a13fa7abf55daedf25b31258b908548f55962c7a, target era originalmente EventTarget & T , pero este cambio (aparentemente) se revirtió accidentalmente durante una fusión en la confirmación 5607f54defce88bc52a0440288f434cafffdb5ce.

La firma actual rompe una gran cantidad de código anterior a 2.0 (como puede imaginar, el código de React está repleto de controladores de eventos) por poco o ningún beneficio (ya que la mayoría del código se basa en event.target , por lo que esto significa seguir confiando en pre -2.0 código como (event.target as any).value , ya que event.target no es genérico.

Estaré encantado de proporcionar un parche, pero me gustaría estar seguro de que SyntheticEvent.target no se degeneró a propósito.

Comentario más útil

No siempre se puede saber el tipo de destino en tiempo de compilación. Hacerlo genérico tiene poco valor.
el objetivo es el origen del evento (que a nadie realmente le importa, podría ser un lapso dentro de un enlace, por ejemplo)
currentTarget es el elemento al que se adjunta el controlador de eventos, por lo que debería preocuparse mucho y escribir en consecuencia si adjuntó un conjunto de datos u otros atributos y tiene la intención de acceder en tiempo de ejecución.

Confiar en el objetivo en lugar de en el objetivo actual es un error de principiante que los morderá antes que después.

Por ejemplo:

  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 se utiliza para compilar, como debería.

Con la 'corrección' fusionada, e.currentTarget no se puede escribir (no puedo acceder a su conjunto de datos sin un error de tipo) y e.target ahora se escribe como HTMLLinkElement, cuando en realidad no hay forma podemos estar seguros de ello. (Es posible que haya hecho clic en el tramo interior.

En teoría, podríamos agregar un segundo genérico a SyntheticEvent, para escribir target, cuando el usuario esté seguro (no hay hijos para el controlador del evento, o todos tienen el mismo tipo). Pero tiene poco valor y es realmente engañoso (porque solo se aplica a casos particulares en los que usar el casting tendría mucho más sentido).
En particular, si no tiene hijos, puede usar currentTarget.

Todos 7 comentarios

Probablemente se trate de un error cometido durante la fusión. Haga un PR.

vea # 11041, # 10784 y muchos más. Es un misterio por qué no se arregla incluso después de la fusión.

No siempre se puede saber el tipo de destino en tiempo de compilación. Hacerlo genérico tiene poco valor.
el objetivo es el origen del evento (que a nadie realmente le importa, podría ser un lapso dentro de un enlace, por ejemplo)
currentTarget es el elemento al que se adjunta el controlador de eventos, por lo que debería preocuparse mucho y escribir en consecuencia si adjuntó un conjunto de datos u otros atributos y tiene la intención de acceder en tiempo de ejecución.

Confiar en el objetivo en lugar de en el objetivo actual es un error de principiante que los morderá antes que después.

Por ejemplo:

  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 se utiliza para compilar, como debería.

Con la 'corrección' fusionada, e.currentTarget no se puede escribir (no puedo acceder a su conjunto de datos sin un error de tipo) y e.target ahora se escribe como HTMLLinkElement, cuando en realidad no hay forma podemos estar seguros de ello. (Es posible que haya hecho clic en el tramo interior.

En teoría, podríamos agregar un segundo genérico a SyntheticEvent, para escribir target, cuando el usuario esté seguro (no hay hijos para el controlador del evento, o todos tienen el mismo tipo). Pero tiene poco valor y es realmente engañoso (porque solo se aplica a casos particulares en los que usar el casting tendría mucho más sentido).
En particular, si no tiene hijos, puede usar currentTarget.

Además, es completamente incorrecto, en un DOMAttributes<SomeType> , obtienes un onClick : MouseEventHandler<SomeType> , luego obtienes EventHandler<MouseEvent<SomeType>> con

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

Absolutamente no puede escribir target de manera diferente a currentTarget. onClick espera un controlador de eventos que tenga el evento de manejo (también conocido como currentTarget) como genérico. No puede ser otra cosa, no se compilará.

@bbenezech

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

Sugiero en su lugar:

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

También tienes ClipboardEvent<T> , CompositionEvent<T> , DragEvent<T> , FocusEvent<T> , KeyboardEvent<T> ...
SyntheticEvent es lo de bajo nivel.

Esto sigue siendo así en el repositorio @types NPM. Cualquier actualización sobre cuándo se publicará

Esto fue cambiado de nuevo. Ver # 12239.

¿Fue útil esta página
0 / 5 - 0 calificaciones