ไม่มีคุณสมบัติ '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 รู้ว่าองค์ประกอบคือ a textareaและจะรู้ถึงคุณสมบัติค่า

สิ่งเดียวกันนี้สามารถทำได้กับองค์ประกอบ 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 Template: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Component: ... this.url = event.target.result;บางครั้งก็ใช้งานไม่ได้เมื่อมันไม่ผิดพลาดerror TS2339: Property 'result' does not exist on type 'EventTarget'ตามที่คุณแนะนำบอก TS เพิ่มเติมเกี่ยวกับเรื่องนี้ในที่ที่HTMLTextAreaElementฉันพยายามHTMLInputElementแล้วก็target.valueไม่มาก ผิดพลาด แต่ภาพไม่แสดง
Jeb50

ฉันรู้สึกประหลาดใจที่เห็นว่าคุณไม่สามารถผ่านประเภทเป็นEventประเภทได้ คุณควรจะใช้Event<HTMLInputElement>เป็นประเภทได้จริงๆ
Ronan

เหตุการณ์ @RoRo มีคุณสมบัติที่คล้ายกันดังต่อไปนี้: target, currentTargetและsrcElement; หนึ่งจะต้องพิมพ์ 3 ประเภททั่วไป; แม้ว่าพวกเขาจะใช้ประเภทเริ่มต้นเช่นEvent<T = any, C = any, S = any>สำหรับที่กล่าวมาข้างต้นก็อาจใช้งานได้ยากกว่าasคำสั่งธรรมดา ฉันยังสามารถจินตนาการ holywar ที่มีศักยภาพสำหรับสิ่งที่ควรจะทั่วไปครั้งแรกหรือtarget currentTargetนอกจากนี้ไลบรารีจำนวนมากยังใช้เหตุการณ์ HTML ไม่ถูกต้องและอาจใส่อะไรก็ได้ที่ต้องการในคุณสมบัติที่กล่าวถึง อาจเป็นสาเหตุเหล่านี้ว่าทำไมพวกเขาไม่ทำมันเป็นยาสามัญในตัว
smnbbrv

สำหรับแถบค้นหาไอออนของฉันฉันใช้(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

เนื่องจากฉันมีคำถามสองข้อที่ค้นหาปัญหาของฉันด้วยวิธีที่แตกต่างกันเล็กน้อยฉันกำลังจำลองคำตอบของฉันเผื่อว่าคุณจะจบลงที่นี่

ในฟังก์ชันที่เรียกว่าคุณสามารถกำหนดประเภทของคุณด้วย:

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

สิ่งนี้จะถือว่าคุณสนใจในtargetทรัพย์สินเท่านั้นซึ่งเป็นกรณีที่พบบ่อยที่สุด หากคุณต้องการเข้าถึงคุณสมบัติอื่น ๆ ของeventโซลูชันที่ครอบคลุมมากขึ้นเกี่ยวข้องกับการใช้ตัว&ดำเนินการแยกประเภท:

event: Event & { target: HTMLInputElement }

คุณยังสามารถเจาะจงมากขึ้นและแทนที่จะใช้HTMLInputElementคุณสามารถใช้เช่นHTMLTextAreaElementสำหรับ textareas


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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.