Property 'value' does not exist on type 'EventTarget': решение 2025

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

«Property 'value' does not exist on type 'EventTarget'» — как перестать бояться и начать типизировать события в TypeScript

Вы когда-нибудь писали обработчик события в TypeScript, пытались получить event.target.value — и тут же получали красное подчёркивание и сообщение: «Property 'value' does not exist on type 'EventTarget'»? Если да — вы не одиноки. На Stack Overflow этот вопрос собрал десятки тысяч просмотров, и он продолжает мучать новичков и опытных разработчиков в 2025 году.

Проблема не в том, что TypeScript «злой» или «сломанный». Всё наоборот: компилятор защищает вас от глупых ошибок, которые могли бы упасть в рантайме. Давайте разберёмся, почему возникает эта ошибка и как её правильно чинить.

Почему TypeScript ругается на event.target.value?

Краткий ответ: event.target имеет тип EventTarget | null. А у EventTarget нет свойства value. У него есть только три метода: addEventListener, removeEventListener и dispatchEvent.

Когда вы пишете:

const handleChange = (event: React.ChangeEvent) => {
  const value = event.target.value; // ❌ Ошибка!
};

TypeScript видит: «Эй, я не знаю, какой конкретно HTML-элемент вызвал это событие. Может быть, это <div>, у которого нет value, а может быть <input> — я не уверен. Поэтому я отказываюсь компилировать такой код».

Это фича, а не баг. TypeScript заставляет вас явно указать, с каким элементом вы работаете.

Топ-3 способа решения (актуально для 2025)

Есть несколько подходов. Мы рассмотрим самые популярные и безопасные.

1. Каст через as HTMLInputElement (быстро, но осторожно)

Самый распространённый способ — привести event.target к нужному типу:

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  const value = (event.target as HTMLInputElement).value;
  console.log(value);
};

Плюсы: просто, понятно, работает.

Минусы: если вы ошиблись и на самом деле событие пришло от <textarea> или <select>, то вы получите undefined в рантайме. Компилятор вас не предупредит.

Лучше использовать этот метод, когда вы абсолютно уверены в типе элемента. Например, в простых формах с одним полем.

2. Использовать event.currentTarget вместо event.target

В TypeScript currentTarget типизирован более строго, чем target. Если вы укажете generic-параметр для события, то currentTarget будет иметь правильный тип:

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  const value = event.currentTarget.value; // ✅ Работает без каста!
};

Важно: currentTarget — это элемент, на который подписан обработчик. Если вы подписались на <input>, то currentTarget всегда будет этим <input>. В отличие от target, который может быть вложенным элементом (например, <span> внутри кнопки).

Плюсы: безопаснее, чем каст, не нужно писать лишних приведений.

Минусы: подходит не для всех сценариев — например, для событий всплытия (bubbling) currentTarget может не совпадать с целевым элементом.

3. Дженерик-функция с проверкой (самый безопасный способ)

Если вы хотите максимальной безопасности и переиспользуемости, напишите вспомогательную функцию, которая проверяет тип элемента:

function getInputValue(event: Event): string | null {
  const target = event.target;
  if (target instanceof HTMLInputElement) {
    return target.value;
  }
  if (target instanceof HTMLTextAreaElement) {
    return target.value;
  }
  return null;
}

// Использование
const handleChange = (event: Event) => {
  const value = getInputValue(event);
  if (value !== null) {
    console.log(value);
  }
};

Плюсы: абсолютная типобезопасность, работает с любыми событиями (не только React), легко тестировать.

Минусы: больше кода, нужно писать вспомогательные функции.

Этот подход особенно полезен, если вы работаете с нативными DOM-событиями, а не с синтетическими событиями React.

А что насчёт React 19 и новых типов в 2025?

В 2025 году TypeScript и React продолжают развиваться. В React 19 улучшили типизацию событий, но проблема с event.target остаётся — это фундаментальное ограничение DOM API. TypeScript не может знать, какой элемент вызвал событие, пока вы ему не скажете.

Однако появилась новая тенденция: использовать strict event handlers с автоматическим выводом типа currentTarget. Многие современные библиотеки (например, MUI, Chakra UI) уже экспортируют строго типизированные обработчики. Рекомендуем следовать их примеру.

Практический чек-лист: как избежать ошибки в будущем

  • Всегда типизируйте аргумент события. Вместо (event) => ... пишите (event: React.ChangeEvent<HTMLInputElement>) => ...
  • Используйте currentTarget вместо target — это уменьшает количество кастов.
  • Если нужен target — делайте проверку через instanceof перед тем, как обращаться к .value.
  • Выносите логику проверки в отдельные функции-хелперы — это улучшает читаемость и переиспользование.
  • Не злоупотребляйте as any — это убивает всю пользу от TypeScript.

Заключение: действуйте осознанно

Ошибка «Property 'value' does not exist on type 'EventTarget'» — это не баг TypeScript, а его суперсила. Компилятор не даёт вам написать код, который может упасть в рантайме. Ваша задача — помочь ему, явно указав тип элемента.

В 2025 году лучшие практики просты: