La propriété 'value' n'existe pas sur le type EventTarget dans TypeScript

118

Donc, le code suivant est dans Angular 4 et je ne peux pas comprendre pourquoi cela ne fonctionne pas comme prévu.

Voici un extrait de mon gestionnaire:

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

Élément HTML:

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

Le code me donne l'erreur:

La propriété 'value' n'existe pas sur le type 'EventTarget'.

Mais comme on peut le voir dans le, console.logcette valeur existe sur le event.target.

Ravy
la source
2
nous pouvons utiliser (e.target as HTMLInputElement) .value
user1162084

Réponses:

147

event.targetvoici un HTMLElementqui est le parent de tous les éléments HTML, mais il n'est pas garanti d'avoir la propriété value. TypeScript détecte cela et renvoie l'erreur. Effectuez un cast event.targetvers l'élément HTML approprié pour vous assurer qu'il s'agit bien de celui HTMLInputElementqui possède une valuepropriété:

(<HTMLInputElement>event.target).value

Selon la documentation :

Tapez le $event

L'exemple ci-dessus convertit le en $eventtant que anytype. Cela simplifie le code à un coût. Il n'y a aucune information de type qui pourrait révéler les propriétés de l'objet événement et éviter des erreurs stupides.

[...]

Le $eventest maintenant un spécifique KeyboardEvent. Tous les éléments n'ont pas de valuepropriété, il est donc converti targeten élément d'entrée.

(Je souligne)

Andrew Li
la source
26
Syntaxe un peu plus proprevar element = ev.target as HTMLElement
Adrian Moisa
Pour moi, HTMLInputElement a fonctionné au lieu de HTMLElement car HTMLElement n'a pas de valeur dans l'interface.
Harsha Vardhini
1
La meilleure approche, à mon avis, est d'avoir onFieldUpdate(event: { target: HTMLInputElement }) {dans la fonction appelée. Voir ma réponse ci-dessous.
belvederef
Pour Angular 9, utilisez la syntaxe "as". event.target as HtmlInputlement
Prescol
87

Passer HTMLInputElement en tant que générique au type d'événement devrait également fonctionner:

onUpdatingServerName(event: React.ChangeEvent<HTMLInputElement>) {
  console.log(event);
  this.newserverName = event.target.value;
}
Mikael Lirbank
la source
14
C'est mieux que les assertions de type.
JamesYin
2
Cela ne fonctionnera pas si la fonction est appelée à partir d'une onChangeréférence de gestionnaire de propriété dans le code React. Le gestionnaire de réaction ne s'attend pas à ce que le type soit défini pour React.ChangeEvent et affichera une erreur de frappe. Je devais revenir à (une variante de) la réponse au lieu choisi, avec un casting: (event.target as HTMLInputElement).value.
Spiralis
Cela a semblé bien fonctionner pour moi dans un composant React. C'est peut-être la version de React? Nous sommes actuellement sur 16.8. *.
hellatan
49

Voici une autre solution qui fonctionne pour moi:

(event.target as HTMLInputElement).value

Cela devrait éliminer l'erreur en informant TS que event.targetc'est un HTMLInputElement, qui a intrinsèquement un value. Avant de spécifier, TS savait probablement que eventseul était un HTMLInputElement, donc selon TS la valeur saisie targetétait une valeur mappée au hasard qui pouvait être n'importe quoi.

Matt S.
la source
4
Cela a été vraiment utile dans React où il a essayé d'interpréter <HTMLInputElement> comme JSX.
Christopher Bradshaw
Hé mec, merci pour le partage! Cette solution me convient.
Carlos Querioz le
16

Je cherchais une solution à une erreur TypeScript similaire avec React:

La propriété 'dataset' n'existe pas sur le type EventTarget dans TypeScript

Je voulais accéder à event.target.datasetun élément de bouton cliqué dans React:

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

Voici comment j'ai pu obtenir la datasetvaleur pour "exister" via 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
la source
1
La question est étiquetée comme angulaire, donc une réponse React semble hors sujet.
John Snow
2
Quoi qu'il en soit ... il y a plusieurs votes, donc cette réponse a été utile aux autres.
Beau Smith
1
Fonctionne comme un charme. onChange={(event: ChangeEvent<HTMLInputElement>): void => { setTextFilter(event.target.value); }}
Vadorequest
3

La façon dont je le fais est la suivante (mieux que l'assertion de type à mon humble avis):

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

Cela suppose que vous n'êtes intéressé que par la targetpropriété, ce qui est le cas le plus courant. Si vous avez besoin d'accéder aux autres propriétés de event, une solution plus complète consiste à utiliser l' &opérateur d'intersection de type:

event: Event & { target: HTMLInputElement }

Il s'agit d'une version de Vue.js mais le concept s'applique à tous les frameworks. Évidemment, vous pouvez aller plus spécifique et au lieu d'utiliser un général, HTMLInputElementvous pouvez utiliser par exemple HTMLTextAreaElementpour les zones de texte.

belvédère
la source
2

Vous devez utiliser event.target.valueprop avec le gestionnaire onChange sinon vous pouvez voir:

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

Ou si vous souhaitez utiliser un autre gestionnaire que onChange, utilisez event.currentTarget.value

JillAndMe
la source
cela fonctionne pour moi mais je ne suis pas sûr que l'utilisation event.currentTarget.valuesoit la meilleure approche.
dczii