A propriedade 'valor' não existe no tipo 'EventTarget'

115

Estou usando o TypeScript versão 2 para um código de componente Angular 2.

Estou recebendo o erro "Propriedade 'valor' não existe no tipo 'EventTarget'" para o código abaixo, qual poderia ser a solução. Obrigado!

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

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

Respostas:

189

Você precisa informar explicitamente ao TypeScript o tipo de HTMLElement que é seu destino.

A maneira de fazer isso é usar um tipo genérico para convertê-lo em um tipo adequado:

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

ou (como você quiser)

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

ou (novamente, questão de preferência)

const target = e.target as HTMLTextAreaElement;

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

Isso permitirá ao TypeScript saber que o elemento é um textareae saberá da propriedade value.

O mesmo poderia ser feito com qualquer tipo de elemento HTML, sempre que você fornecer ao TypeScript um pouco mais de informação sobre seus tipos, ele retribuirá com dicas adequadas e, claro, menos erros.

Para tornar mais fácil para o futuro, você pode definir diretamente um evento com o tipo de seu destino:

// 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
fonte
@smnbbrv meu caso é um local de arquivo img, em seguida, exibir o img, com base no SO Template: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Componente: ... this.url = event.target.result;Algum funciona, às vezes não, quando não err está é error TS2339: Property 'result' does not exist on type 'EventTarget'como você sugeriu TS dizer mais sobre isso, no lugar HTMLTextAreaElementeu tentei HTMLInputElement, em seguida, target.valuenão mais errar, mas a imagem não está sendo exibida.
Jeb50
Fiquei surpreso ao ver que não era possível passar um tipo para o Eventtipo. Você realmente deve ser capaz de usar Event<HTMLInputElement>como um tipo.
Ronan
@RoRo evento tem as seguintes propriedades semelhantes: target, currentTargete srcElement; seria necessário digitar 3 tipos genéricos; mesmo se eles usarem tipos padrão, por exemplo, Event<T = any, C = any, S = any>para o mencionado acima, pode ser mais desconfortável de usar do que a asinstrução simples . Eu também poderia imaginar uma guerra sagrada potencial para o que deveria ser primeiro genérico: targetou currentTarget. Além disso, muitas bibliotecas abusam de eventos HTML e podem potencialmente colocar o que quiserem nas propriedades mencionadas. Provavelmente essas são as razões pelas quais eles não o fizeram como genéricos
embutidos
Para minha barra de pesquisa de íons, estou usando(ionChangeEvent.target as HTMLIonInputElement).value as string
Nuvem
40

Aqui está a abordagem simples que usei:

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

O erro mostrado pelo compilador TypeScript desapareceu e o código funciona.

Torsten Barthel
fonte
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));

Talvez algo como o acima possa ajudar. Altere-o com base no código real. O problema é ........ alvo ['valor']

Ahmed
fonte
2

Eu acredito que deve funcionar, mas de alguma forma não sou capaz de identificar. Outra abordagem pode ser,

<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);
       }
}
micronyks
fonte
2

Aqui está outra abordagem simples, eu usei;

    inputChange(event: KeyboardEvent) {      
    const target = event.target as HTMLTextAreaElement;
    var activeInput = target.id;
    }
Burak Odabaş
fonte
2

Como cheguei a duas questões buscando meu problema de uma forma ligeiramente diferente, estou replicando minha resposta caso você acabe aqui.

Na função chamada, você pode definir seu tipo com:

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

Isso pressupõe que você está interessado apenas na targetpropriedade, que é o caso mais comum. Se você precisar acessar as outras propriedades de event, uma solução mais abrangente envolve o uso do &operador de interseção de tipo:

event: Event & { target: HTMLInputElement }

Você também pode ser mais específico e, em vez de usar, HTMLInputElementpode usar, por exemplo, HTMLTextAreaElementpara áreas de texto.

Belvederef
fonte
1

Aqui está mais uma maneira de especificar 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);
    }
}

qiAlex
fonte