La propiedad 'valor' no existe en el tipo 'EventTarget'

115

Estoy usando TypeScript Versión 2 para un código de componente Angular 2.

Recibo el error "La propiedad 'valor' no existe en el tipo 'EventTarget'" para el código siguiente, cuál podría ser la solución. ¡Gracias!

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

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
fuente

Respuestas:

189

Debe indicar explícitamente a TypeScript el tipo de HTMLElement que es su objetivo.

La forma de hacerlo es usar un tipo genérico para convertirlo en un tipo adecuado:

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

o (como quieras)

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

o (de nuevo, cuestión de preferencia)

const target = e.target as HTMLTextAreaElement;

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

Esto le permitirá a TypeScript saber que el elemento es un textareay conocerá la propiedad value.

Lo mismo se puede hacer con cualquier tipo de elemento HTML, siempre que le brinde a TypeScript un poco más de información sobre sus tipos, se lo devolverá con las sugerencias adecuadas y, por supuesto, con menos errores.

Para que sea más fácil para el futuro, es posible que desee definir directamente un evento con el tipo de su objetivo:

// 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
fuente
@smnbbrv mi caso es una ubicación de archivo img y luego muestra el img, basado en SO Plantilla: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Componente: ... this.url = event.target.result;A veces funciona, a veces no, cuando no es err es error TS2339: Property 'result' does not exist on type 'EventTarget'Como sugirió, dígale a TS más al respecto, en el lugar HTMLTextAreaElementque probé, HTMLInputElemententonces target.valueno más err pero la imagen no se muestra.
Jeb50
Me sorprendió ver que no se podía pasar un tipo a otro Event. Realmente debería poder usarlo Event<HTMLInputElement>como tipo.
Ronan
Evento @RoRo tiene las siguientes propiedades similares: target, currentTargety srcElement; habría que escribir 3 tipos genéricos; incluso si usan tipos predeterminados, por ejemplo, Event<T = any, C = any, S = any>para lo mencionado anteriormente, podría ser más incómodo de usar que la simple asdeclaración. También podría imaginar una posible guerra santa para lo que debería ser primero genérico: targeto currentTarget. Además, muchas bibliotecas abusan del evento HTML y potencialmente pueden poner lo que quieran en las propiedades mencionadas. Probablemente estas son las razones por las que no lo hicieron como genéricos
integrados
Para mi barra de búsqueda de iones, estoy usando(ionChangeEvent.target as HTMLIonInputElement).value as string
Cloud
40

Aquí está el enfoque simple que utilicé:

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

El error mostrado por el compilador de TypeScript desapareció y el código funciona.

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

Quizás algo como lo anterior podría ayudar. Cámbielo según el código real. El problema es ........ objetivo ['valor']

Ahmed
fuente
2

Creo que debe funcionar, pero no puedo identificar de ninguna manera. Otro enfoque puede 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
fuente
2

Aquí hay otro enfoque simple que utilicé;

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

Como llegué a dos preguntas buscando mi problema de una manera ligeramente diferente, estoy replicando mi respuesta en caso de que termines aquí.

En la función llamada, puede definir su tipo con:

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

Esto supone que solo está interesado en la targetpropiedad, que es el caso más común. Si necesita acceder a las otras propiedades de event, una solución más completa implica el uso del &operador de intersección de tipo:

event: Event & { target: HTMLInputElement }

También puede ser más específico y, en lugar de usar HTMLInputElement, puede usar, por ejemplo, HTMLTextAreaElementpara áreas de texto.

Belvederef
fuente
1

Aquí hay una forma más 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
fuente