Свойство value не существует для типа EventTarget в TypeScript


121

Итак, следующий код находится в Angular 4, и я не могу понять, почему он работает не так, как ожидалось.

Вот фрагмент моего обработчика:

onUpdatingServerName(event: Event) {
  console.log(event);
  this.newserverName = event.target.value; //this wont work
}

HTML-элемент:

<input type="text" class="form-control" (input)="onUpdatingServerName($event)">

Код дает мне ошибку:

Свойство value не существует для типа EventTarget.

Но, как видно на рисунке, console.logэто значение существует в event.target.


2
мы можем использовать (e.target как HTMLInputElement) .value
user1162084 01

Ответы:


149

event.targetвот HTMLElementродительский элемент всех HTML-элементов, но не гарантируется наличие свойства value. TypeScript обнаруживает это и выдает ошибку. Приведите event.targetк соответствующему элементу HTML, чтобы убедиться, HTMLInputElementчто у него есть valueсвойство:

(<HTMLInputElement>event.target).value

Согласно документации :

Введите $event

В приведенном выше примере $eventиспользуется anyтип. Это упрощает код за счет стоимости. Нет информации о типе, которая могла бы раскрыть свойства объекта события и предотвратить глупые ошибки.

[...]

$eventТеперь специфический KeyboardEvent. Не все элементы имеют valueсвойство, поэтому оно targetпреобразуется во входной элемент.

(Акцент мой)


26
Немного более чистый синтаксисvar element = ev.target as HTMLElement
Адриан Мойса 07

Для меня HTMLInputElement работал вместо HTMLElement, поскольку HTMLElement не имеет значения в интерфейсе.
Харша Вардхини,

1
На мой взгляд, лучший подход заключается onFieldUpdate(event: { target: HTMLInputElement }) {в вызываемой функции. Смотрите мой ответ ниже.
belvederef

Для Angular 9 используйте синтаксис «as». event.target as HtmlInputlement
Prescol,

88

Передача HTMLInputElement в качестве универсального для типа события также должна работать:

onUpdatingServerName(event: React.ChangeEvent<HTMLInputElement>) {
  console.log(event);
  this.newserverName = event.target.value;
}

14
Это лучше, чем утверждения типа.
JamesYin 08

2
Это не будет работать, если функция вызывается, например, из onChangeссылки обработчика свойства в коде React. Обработчик реакции не ожидает, что тип будет установлен для React.ChangeEvent, и покажет ошибку ввода. Я должен был вернуться к (вариант) выбранного ответа вместо с броском: (event.target as HTMLInputElement).value.
Spiralis

Мне показалось, что это отлично работает в компоненте React. Может дело в версии React? Сейчас мы находимся на версии 16.8. *.
hellatan

49

Вот еще одно исправление, которое мне подходит:

(event.target as HTMLInputElement).value

Это должно избавить от ошибки, сообщив TS, что event.targetэто файл HTMLInputElement, который по своей сути имеет расширение value. Перед указанием TS, вероятно, знала только, что это eventодно HTMLInputElement, поэтому, согласно TS, введенное значение targetбыло некоторым случайно отображенным значением, которое могло быть чем угодно.


4
Это было действительно полезно в React, где он пытался интерпретировать <HTMLInputElement> как JSX.
Christopher Bradshaw

Эй, чувак, спасибо, что поделился! Это решение мне подходит.
Карлос Кериос,

16

Я искал решение аналогичной ошибки TypeScript с React:

Свойство dataset не существует для типа EventTarget в TypeScript.

Я хотел добраться до event.target.datasetэлемента с нажатой кнопкой в ​​React:

<button
  onClick={onClickHandler}
  data-index="4"
  data-name="Foo Bar"
>
  Delete Candidate
</button>

Вот как я смог заставить datasetзначение «существовать» через TypeScript:

const onClickHandler = (event: React.MouseEvent<HTMLButtonElement>) => {
  const { name, index } = (event.target as HTMLButtonElement).dataset
  console.log({ name, index })
  // do stuff with name and index…
}

1
Вопрос помечен как Angular, поэтому ответ React кажется не по теме.
Джон Сноу

2
Несмотря на это ... он получил несколько голосов "за", поэтому этот ответ был полезен другим.
Бо Смит

1
Работает как шарм. onChange={(event: ChangeEvent<HTMLInputElement>): void => { setTextFilter(event.target.value); }}
Vadorequest

4

Я делаю это следующим образом (лучше, чем утверждение типа imho):

onFieldUpdate(event: { target: HTMLInputElement }) {
  this.$emit('onFieldUpdate', event.target.value);
}

Это предполагает, что вас интересует только targetсобственность, что является наиболее распространенным случаем. Если вам нужно получить доступ к другим свойствам event, более комплексное решение включает использование &оператора пересечения типов:

event: Event & { target: HTMLInputElement }

Это версия Vue.js, но концепция применима ко всем фреймворкам. Очевидно, вы можете пойти более конкретным образом и вместо общего HTMLInputElementиспользования, например, HTMLTextAreaElementдля текстовых полей.


2

Вы должны использовать event.target.valueопору с обработчиком onChange, если вы не видите:

index.js:1437 Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

Или, если вы хотите использовать другой обработчик, кроме onChange, используйте event.currentTarget.value


это работает для меня, но я не уверен, что event.currentTarget.valueэто лучший подход.
dczii

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.