La propiedad 'valor' no existe en el tipo EventTarget en TypeScript

118

Entonces, el siguiente código está en Angular 4 y no puedo entender por qué no funciona como se esperaba.

Aquí hay un fragmento de mi controlador:

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

Elemento HTML:

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

El código me da el error:

La propiedad 'valor' no existe en el tipo 'EventTarget'.

Pero como se puede ver en el, console.logese valor existe en el event.target.

Ravy
fuente
2
podemos usar (e.target como HTMLInputElement) .value
user1162084

Respuestas:

146

event.targetaquí hay un HTMLElementque es el padre de todos los elementos HTML, pero no se garantiza que tenga la propiedad value. TypeScript detecta esto y arroja el error. Transmitir event.targetal elemento HTML apropiado para asegurarse de que sea el HTMLInputElementque tenga una valuepropiedad:

(<HTMLInputElement>event.target).value

Según la documentación :

Escribe el $event

El ejemplo anterior convierte el $eventcomo un anytipo. Eso simplifica el código con un costo. No hay información de tipo que pueda revelar las propiedades del objeto del evento y evitar errores tontos.

[...]

El $eventes ahora una específica KeyboardEvent. No todos los elementos tienen una valuepropiedad, por lo que se convierte targeten un elemento de entrada.

(El énfasis es mío)

Andrew Li
fuente
26
Sintaxis un poco más limpiavar element = ev.target as HTMLElement
Adrian Moisa
Para mí, HTMLInputElement funcionó en lugar de HTMLElement ya que HTMLElement no tiene valor en la interfaz.
Harsha Vardhini
El mejor enfoque, en mi opinión, es tener onFieldUpdate(event: { target: HTMLInputElement }) {en la función llamada. Vea mi respuesta a continuación.
belvederef
Para Angular 9 use la sintaxis "as". event.target as HtmlInputlement
Prescol
86

Pasar HTMLInputElement como genérico al tipo de evento también debería funcionar:

onUpdatingServerName(event: React.ChangeEvent<HTMLInputElement>) {
  console.log(event);
  this.newserverName = event.target.value;
}
Mikael Lirbank
fuente
14
Esto es mejor que las afirmaciones de tipo.
JamesYin
2
Sin onChangeembargo, esto no funcionará si se llama a la función desde, por ejemplo, una referencia de controlador de propiedad en el código de React. El controlador de reacción no espera que el tipo se establezca para React.ChangeEvent y mostrará un error de escritura. Tenía que volver a (una variante de) la respuesta seleccionada por el contrario, con un reparto: (event.target as HTMLInputElement).value.
Spiralis
Esto pareció funcionarme bien en un componente de React. ¿Quizás es la versión de React? Actualmente estamos en 16.8. *.
hellatan
49

Aquí hay otra solución que funciona para mí:

(event.target as HTMLInputElement).value

Eso debería eliminar el error al hacerle saber a TS que event.targetes un HTMLInputElement, que inherentemente tiene un value. Antes de especificar, TS probablemente solo sabía que eventsolo era un HTMLInputElement, por lo tanto, según TS, el tecleado targetera un valor mapeado aleatoriamente que podría ser cualquier cosa.

Matt S.
fuente
4
Esto fue realmente útil en React, donde intentó interpretar <HTMLInputElement> como JSX.
Christopher Bradshaw
¡Oye, gracias por compartir! Esta solución me queda bien.
Carlos Querioz
16

Estaba buscando una solución a un error similar de TypeScript con React:

La propiedad 'conjunto de datos' no existe en el tipo EventTarget en TypeScript

Quería llegar a event.target.datasetun elemento de botón en el que se hizo clic en React:

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

Así es como pude obtener el datasetvalor para "existir" a través de 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…
}
Beau Smith
fuente
1
La pregunta está etiquetada como Angular, por lo que una respuesta de React parece fuera de tema.
John Snow
2
Independientemente ... tiene varios votos a favor, por lo que esta respuesta ha sido útil para otros.
Beau Smith
1
Funciona de maravilla. onChange={(event: ChangeEvent<HTMLInputElement>): void => { setTextFilter(event.target.value); }}
Vadorequest
2

Debería usar event.target.valueprop con el controlador onChange si no puede ver:

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`.

O si desea utilizar otro controlador que no sea onChange, utilice event.currentTarget.value

JillAndMe
fuente
esto funciona para mí, pero no estoy seguro de que usar event.currentTarget.valuesea ​​el mejor enfoque.
dczii
2

La forma en que lo hago es la siguiente (mejor que la afirmación de tipo en mi humilde opinión):

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

Esto supone que solo está interesado en la targetpropiedad, que es el caso más común. Si necesita acceder a las otras propiedades de event, una solución más completa implica el uso del &operador de intersección de tipo:

event: Event & { target: HTMLInputElement }

Esta es una versión de Vue.js, pero el concepto se aplica a todos los marcos. Obviamente, puede ir más específico y en lugar de usar un general HTMLInputElementpuede usar, por ejemplo, HTMLTextAreaElementpara áreas de texto.

Belvederef
fuente