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


119

Я использую TypeScript версии 2 для кода компонента Angular 2.

Я получаю сообщение об ошибке «Значение свойства не существует для типа EventTarget» для приведенного ниже кода. Какое может быть решение. Спасибо!

e.target.value.match (/ \ S + / g) || []). длина

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

Ответы:


195

Вам необходимо явно указать TypeScript тип HTMLElement, который является вашей целью.

Способ сделать это - использовать общий тип, чтобы привести его к правильному типу:

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

или (как угодно)

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

или (опять же, вопрос предпочтения)

const target = e.target as HTMLTextAreaElement;

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

Это позволит TypeScript узнать, что это элемент, textareaи узнать о свойстве value.

То же самое можно сделать с любым типом HTML-элемента: всякий раз, когда вы даете TypeScript немного больше информации об их типах, он окупается правильными подсказками и, конечно же, меньшим количеством ошибок.

Чтобы упростить задачу в будущем, вы можете напрямую определить событие с типом его цели:

// 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 мой случай тогда место IMG файл отображения IMG, основанный на SO Шаблон: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Компонент: ... this.url = event.target.result;Когда - нибудь не работает , иногда нет, когда это не свойственно ошибаться , error TS2339: Property 'result' does not exist on type 'EventTarget'как вы предложили рассказать TS больше об этом, в том месте , HTMLTextAreaElementя пытался HTMLInputElementтогда target.valueне более ошибка, но изображение не отображается.
Jeb50

Я был удивлен, увидев, что вы не можете передать тип в Eventтип. Вы действительно должны уметь использовать Event<HTMLInputElement>как тип.
Ронан

@RoRo событие имеет следующие свойства , аналогичные свойства: target, currentTargetи srcElement; нужно ввести 3 универсальных типа; даже если они используют типы по умолчанию, например, Event<T = any, C = any, S = any>для упомянутых выше, это может быть более неудобно, чем простой asоператор. Я также мог вообразить потенциальный холивар для того, что должно быть первым родовым: targetили currentTarget. Кроме того, многие библиотеки злоупотребляют HTML-событиями и потенциально могут поместить все, что захотят, в упомянутые свойства. Вероятно, это причины, по которым они не сделали это как встроенные дженерики
smnbbrv

Для моей панели поиска ion я использую(ionChangeEvent.target as HTMLIonInputElement).value as string
Cloud

42

Вот простой подход, который я использовал:

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

Ошибка, отображаемая компилятором TypeScript, исчезла, и код работает.


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

Может быть, поможет что-то подобное. Измените его на основе реального кода. Проблема в том ........ цель ['значение']


2

Я считаю, что это должно сработать, но никакие способы я не могу определить. Другой подход может быть,

<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

Вот еще один простой подход, который я использовал;

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

2

Поскольку я ответил на два вопроса, пытаясь найти свою проблему немного по-другому, я повторяю свой ответ на случай, если вы окажетесь здесь.

В вызываемой функции вы можете определить свой тип с помощью:

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

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

event: Event & { target: HTMLInputElement }

Вы также можете сделать более конкретным и вместо использования HTMLInputElementвы можете использовать, например, HTMLTextAreaElementдля текстовых полей.


1

Вот еще один способ указать 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);
    }
}

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