Thuộc tính 'giá trị' không tồn tại trên loại 'EventTarget'


112

Tôi đang sử dụng TypeScript Phiên bản 2 cho mã thành phần Angular 2.

Tôi nhận được lỗi "Giá trị 'thuộc tính' không tồn tại trên loại 'Mục tiêu sự kiện'" cho mã bên dưới, giải pháp có thể là gì. Cảm ơn!

e.target.value.match (/ \ S + / g) || []).chiều dài

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

Câu trả lời:


186

Bạn cần phải cho TypeScript biết rõ ràng loại HTMLElement là mục tiêu của bạn.

Cách thực hiện là sử dụng kiểu chung để truyền nó thành kiểu thích hợp:

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

hoặc (tùy thích)

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

hoặc (một lần nữa, vấn đề ưu tiên)

const target = e.target as HTMLTextAreaElement;

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

Điều này sẽ cho TypeScript biết rằng phần tử là textarea và nó sẽ biết thuộc tính giá trị.

Điều tương tự cũng có thể được thực hiện với bất kỳ loại phần tử HTML nào, bất cứ khi nào bạn cung cấp cho TypeScript thêm một chút thông tin về các loại của chúng, nó sẽ trả lại cho bạn những gợi ý thích hợp và tất nhiên là ít lỗi hơn.

Để giúp cho tương lai dễ dàng hơn, bạn có thể muốn xác định trực tiếp một sự kiện với loại mục tiêu của nó:

// 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 Trường hợp của tôi là một vị trí tệp img sau đó hiển thị img, dựa trên SO Mẫu: <img [src]="url"> <br/> <input type='file' (change)="showImg($event)">Thành phần: ... this.url = event.target.result;Đôi khi hoạt động đôi khi không, khi nó không lỗi error TS2339: Property 'result' does not exist on type 'EventTarget'Như bạn đã đề xuất cho TS biết thêm về nó, tại nơi HTMLTextAreaElementtôi đã thử HTMLInputElementrồi target.valuekhông còn nữa lỗi nhưng hình ảnh không hiển thị.
Jeb50

Tôi rất ngạc nhiên khi thấy rằng bạn không thể chuyển một kiểu vào Eventkiểu. Bạn thực sự có thể sử dụng Event<HTMLInputElement>như một loại.
Ronan

@RoRo sự kiện đã sau tính chất tương tự: target, currentTargetsrcElement; người ta sẽ cần nhập 3 kiểu chung chung; ngay cả khi họ sử dụng các kiểu mặc định, ví dụ như Event<T = any, C = any, S = any>đã đề cập ở trên, nó có thể khó sử dụng hơn ascâu lệnh đơn giản . Tôi cũng có thể tưởng tượng một cuộc thánh chiến tiềm năng cho những gì nên là chung chung đầu tiên: targethoặc currentTarget. Ngoài ra, nhiều thư viện lạm dụng sự kiện HTML và có thể đưa bất kỳ thứ gì họ muốn vào các thuộc tính được đề cập. Có lẽ đây là những lý do tại sao họ không làm điều đó như là thuốc chung tích hợp
smnbbrv

Đối với thanh tìm kiếm ion của tôi, tôi đang sử dụng(ionChangeEvent.target as HTMLIonInputElement).value as string
Cloud

40

Đây là cách tiếp cận đơn giản mà tôi đã sử dụng:

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

Lỗi được hiển thị bởi trình biên dịch TypeScript đã biến mất và mã hoạt động.


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

Có thể một cái gì đó như trên có thể giúp ích. Thay đổi nó dựa trên mã thực. Vấn đề là ........ target ['value']


2

Tôi tin rằng nó phải hoạt động nhưng bất kỳ cách nào tôi không thể xác định được. Cách tiếp cận khác có thể là,

<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

Đây là một cách tiếp cận đơn giản khác, tôi đã sử dụng;

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

2

Vì tôi đã đạt đến hai câu hỏi tìm kiếm vấn đề của mình theo một cách hơi khác, tôi sẽ lặp lại câu trả lời của mình trong trường hợp bạn kết thúc ở đây.

Trong hàm được gọi, bạn có thể xác định kiểu của mình bằng:

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

Điều này giả định rằng bạn chỉ quan tâm đến targettài sản, đây là trường hợp phổ biến nhất. Nếu bạn cần truy cập các thuộc tính khác của event, một giải pháp toàn diện hơn liên quan đến việc sử dụng &toán tử giao nhau kiểu:

event: Event & { target: HTMLInputElement }

Bạn cũng có thể đi cụ thể hơn và thay vì sử dụng, HTMLInputElementbạn có thể sử dụng vd HTMLTextAreaElementcho textareas.


1

Đây là một cách khác để chỉ định 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);
    }
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.