Definitelytyped: Сделайте React.SyntheticEvent.target универсальным для T, а не React.SyntheticEvent.currentTarget

Созданный на 26 сент. 2016  ·  7Комментарии  ·  Источник: DefinitelyTyped/DefinitelyTyped

В настоящее время подпись Typescript 2.0 для SyntheticEvent React выглядит так:

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

Согласно фиксации a13fa7abf55daedf25b31258b908548f55962c7a, target изначально было EventTarget & T , но это изменение (по-видимому) случайно было отменено во время слияния в фиксации 5607f54defce88bc52a0440288f434cafffdb5ce.

Текущая подпись нарушает большую часть кода до версии 2.0 (как вы можете себе представить, код React изобилует обработчиками событий) практически без пользы (поскольку большая часть кода полагается на event.target , поэтому это означает, что все еще полагается на предварительную версию). -2.0 кода, например (event.target as any).value , поскольку event.target не является универсальным.

Я буду рад предоставить патч, но я хотел бы убедиться, что SyntheticEvent.target не был деобенифицирован намеренно.

Самый полезный комментарий

Вы не всегда можете определить тип цели во время компиляции. Делать его универсальным не имеет большого значения.
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.

Все 7 Комментарий

Вероятно, это ошибка, сделанная при слиянии. Пожалуйста, сделайте пиар.

см. # 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. 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.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги