Właściwość „wartość” nie istnieje w typie „EventTarget”


115

Używam TypeScript w wersji 2 dla kodu składnika Angular 2.

Otrzymuję błąd „Wartość właściwości” nie istnieje dla typu „EventTarget” dla poniższego kodu, jakie może być rozwiązanie. Dzięki!

e.target.value.match (/ \ S + / g) || []).długość

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);
}
}

Odpowiedzi:


189

Musisz jawnie podać TypeScript typ elementu HTMLElement, który jest Twoim celem.

Aby to zrobić, użyj typu ogólnego, aby rzutować go na właściwy typ:

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

lub (jak chcesz)

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

lub (znowu, kwestia preferencji)

const target = e.target as HTMLTextAreaElement;

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

Dzięki temu TypeScript będzie wiedział, że element jest plikiem textarea i będzie wiedział o właściwości value.

To samo można zrobić z każdym rodzajem elementu HTML, ilekroć podasz TypeScript nieco więcej informacji o ich typach, odwdzięczy się to odpowiednimi wskazówkami i oczywiście mniejszą liczbą błędów.

Aby ułatwić sobie na przyszłość, możesz chcieć bezpośrednio zdefiniować zdarzenie z typem jego celu:

// 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 mój przypadek to lokalizacja pliku img, a następnie wyświetl img, w oparciu o Szablon SO : <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Składnik: ... this.url = event.target.result;Czasami działa czasami nie, jeśli nie jest to błąd error TS2339: Property 'result' does not exist on type 'EventTarget'Tak jak zasugerowałeś, powiedz TS więcej o tym, w miejscu, HTMLTextAreaElementktóre próbowałem, HTMLInputElementa potem target.valuenie więcej err, ale obraz się nie wyświetla.
Jeb50

Zaskoczyło mnie, że nie można przekazać typu do Eventczcionki. Naprawdę powinieneś być w stanie użyć Event<HTMLInputElement>jako typu.
Ronan

Zdarzenie @RoRo ma następujące właściwości podobne: target, currentTargeti srcElement; należałoby wpisać 3 typy ogólne; nawet jeśli używają domyślnych typów, np. Event<T = any, C = any, S = any>dla wyżej wymienionych, może być bardziej niewygodne w użyciu niż proste asstwierdzenie. Mogę również wyobrazić sobie potencjalny holywar dla tego, co powinno być najpierw ogólne: targetlub currentTarget. Ponadto wiele bibliotek nadużywa zdarzenia HTML i może potencjalnie umieścić wszystko, czego chcą, we wspomnianych właściwościach. Prawdopodobnie są to powody, dla których nie zrobili tego jako wbudowane
typy

Na moim pasku wyszukiwania jonów używam(ionChangeEvent.target as HTMLIonInputElement).value as string
Cloud

40

Oto proste podejście, którego użyłem:

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

Błąd wyświetlany przez kompilator TypeScript zniknął i kod działa.


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));

Może coś takiego jak powyższe mogłoby pomóc. Zmień to w oparciu o rzeczywisty kod. Problem jest ........ target ['value']


2

Uważam, że to musi działać, ale nie mogę zidentyfikować żadnych sposobów. Innym podejściem może być:

<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

Oto inne proste podejście, którego użyłem;

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

2

Ponieważ dotarłem do dwóch pytań, szukając mojego problemu w nieco inny sposób, powtarzam swoją odpowiedź na wypadek, gdybyś tu znalazł się.

W wywołanej funkcji możesz zdefiniować swój typ za pomocą:

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

Zakłada się, że interesuje Cię tylko targetnieruchomość, co jest najczęstszym przypadkiem. Jeśli chcesz uzyskać dostęp do innych właściwości programu event, bardziej kompleksowe rozwiązanie obejmuje użycie &operatora przecięcia typu:

event: Event & { target: HTMLInputElement }

Możesz również przejść bardziej szczegółowo i zamiast HTMLInputElementużywać, na przykład, HTMLTextAreaElementdla obszarów tekstowych.


1

Oto jeszcze jeden sposób określenia 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);
    }
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.