La proprietà "value" non esiste nel tipo "EventTarget"


115

Sto usando TypeScript versione 2 per un codice componente Angular 2.

Ricevo l'errore "La proprietà" valore "non esiste nel tipo" EventTarget "" per il codice sottostante, quale potrebbe essere la soluzione. Grazie!

e.target.value.match (/ \ S + / g) || []).lunghezza

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
selector: 'text-editor',
template: `
<textarea (keyup)="emitWordCount($event)"></textarea>
 `
 })
  export class TextEditorComponent {
   @Output() countUpdate = new EventEmitter<number>();

emitWordCount(e: Event) {
    this.countUpdate.emit(
        (e.target.value.match(/\S+/g) || []).length);
}
}

Risposte:


189

Devi dire esplicitamente a TypeScript il tipo di HTMLElement che è il tuo obiettivo.

Il modo per farlo è usare un tipo generico per eseguire il cast su un tipo appropriato:

this.countUpdate.emit((<HTMLTextAreaElement>e.target).value./*...*/)

o (come preferisci)

this.countUpdate.emit((e.target as HTMLTextAreaElement).value./*...*/)

o (ancora una volta, questione di preferenza)

const target = e.target as HTMLTextAreaElement;

this.countUpdate.emit(target.value./*...*/)

Ciò consentirà a TypeScript di sapere che l'elemento è un file textarea e conoscerà la proprietà value.

Lo stesso potrebbe essere fatto con qualsiasi tipo di elemento HTML, ogni volta che fornisci a TypeScript un po 'più di informazioni sui loro tipi ti ripaga con suggerimenti adeguati e ovviamente meno errori.

Per rendere più facile per il futuro potresti voler definire direttamente un evento con la tipologia del suo target:

// create a new type HTMLElementEvent that has a target of type you pass
// type T must be a HTMLElement (e.g. HTMLTextAreaElement extends HTMLElement)
type HTMLElementEvent<T extends HTMLElement> = Event & {
  target: T; 
  // probably you might want to add the currentTarget as well
  // currentTarget: T;
}

// use it instead of Event
let e: HTMLElementEvent<HTMLTextAreaElement>;

console.log(e.target.value);

// or in the context of the given example
emitWordCount(e: HTMLElementEvent<HTMLTextAreaElement>) {
  this.countUpdate.emit(e.target.value);
}

@smnbbrv mio caso è un percorso di file img quindi visualizzare l'IMG, sulla base di SO Template: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Componente: ... this.url = event.target.result;A volte funziona a volte non, quando non è err è error TS2339: Property 'result' does not exist on type 'EventTarget'come lei ha suggerito TS dica di più su di esso, nel posto HTMLTextAreaElementho provato HTMLInputElementallora target.valuenon più err ma l'immagine non viene visualizzata.
Jeb50

Sono stato sorpreso di vedere che non è stato possibile passare un tipo nel Eventtipo. Dovresti davvero essere in grado di usare Event<HTMLInputElement>come tipo.
Ronan

Evento @RoRo ha le seguenti proprietà simili: target, currentTargete srcElement; sarebbe necessario digitare 3 tipi generici; anche se usano tipi predefiniti, ad esempio Event<T = any, C = any, S = any>per quanto sopra menzionato, potrebbe essere più scomodo da usare rispetto alla semplice asdichiarazione. Potrei anche immaginare una potenziale guerra santa per quello che dovrebbe essere il primo generico: targeto currentTarget. Inoltre, molte biblioteche abusano dell'evento HTML e possono potenzialmente mettere tutto ciò che vogliono nelle proprietà menzionate. Probabilmente questi sono i motivi per cui non l'hanno fatto come generici
incorporati

Per la mia barra di ricerca ionica, sto usando(ionChangeEvent.target as HTMLIonInputElement).value as string
Cloud

40

Ecco il semplice approccio che ho usato:

const element = event.currentTarget as HTMLInputElement
const value = element.value

L'errore mostrato dal compilatore TypeScript è scomparso e il codice funziona.


5
fromEvent<KeyboardEvent>(document.querySelector('#searcha') as HTMLInputElement , 'keyup')
    .pipe(
      debounceTime(500),
      distinctUntilChanged(),
      map(e  => {
            return e.target['value']; // <-- target does not exist on {}
        })
    ).subscribe(k => console.log(k));

Forse qualcosa di simile potrebbe aiutare. Modificalo in base al codice reale. Il problema è ........ target ["value"]


2

Credo che debba funzionare, ma in qualsiasi modo non sono in grado di identificarlo. Un altro approccio può essere,

<textarea (keyup)="emitWordCount(myModel)" [(ngModel)]="myModel"></textarea>


export class TextEditorComponent {
   @Output() countUpdate = new EventEmitter<number>();

   emitWordCount(model) {
       this.countUpdate.emit(
         (model.match(/\S+/g) || []).length);
       }
}

2

Ecco un altro semplice approccio che ho utilizzato;

    inputChange(event: KeyboardEvent) {      
    const target = event.target as HTMLTextAreaElement;
    var activeInput = target.id;
    }

2

Dato che ho raggiunto due domande cercando il mio problema in un modo leggermente diverso, sto replicando la mia risposta nel caso in cui tu finisca qui.

Nella funzione chiamata, puoi definire il tuo tipo con:

emitWordCount(event: { target: HTMLInputElement }) {
  this.countUpdate.emit(event.target.value);
}

Ciò presuppone che tu sia interessato solo alla targetproprietà, che è il caso più comune. Se è necessario accedere alle altre proprietà di event, una soluzione più completa prevede l'utilizzo &dell'operatore di intersezione del tipo:

event: Event & { target: HTMLInputElement }

Puoi anche andare più specifico e invece di usare HTMLInputElementpuoi usare ad esempio HTMLTextAreaElementper le aree di testo.


1

Ecco un altro modo per specificare event.target:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
    selector: 'text-editor',
    template: `<textarea (keyup)="emitWordCount($event)"></textarea>`
})
export class TextEditorComponent {

   @Output() countUpdate = new EventEmitter<number>();

    emitWordCount({ target = {} as HTMLTextAreaElement }) { // <- right there

        this.countUpdate.emit(
          // using it directly without `event`
            (target.value.match(/\S+/g) || []).length);
    }
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.