ChatGPT解决这个技术问题 Extra ChatGPT

“EventTarget”类型上不存在属性“值”

我将 TypeScript 版本 2 用于 Angular 2 组件代码。

对于下面的代码,我收到错误“'EventTarget' 类型上不存在属性'值'”,可能是什么解决方案。谢谢!

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

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);
  }
}
tektutorialshub.com/angular/… 我认为这将回答问题

s
smnbbrv

您需要明确告诉 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 没有更多错误但图像未显示。
看到您无法将类型传递给 Event 类型,我感到很惊讶。您确实应该能够使用 Event<HTMLInputElement> 作为类型。
@RoRo 事件具有以下类似属性:targetcurrentTargetsrcElement;需要输入 3 个泛型类型;即使他们使用默认类型,例如上面提到的 Event<T = any, C = any, S = any>,它也可能比简单的 as 语句更不舒服。我还可以想象一场潜在的圣战,首先应该是通用的:targetcurrentTarget。此外,许多库滥用 HTML 事件,并可能将他们想要的任何内容放在提到的属性中。可能这些是他们没有将其作为内置泛型的原因
对于我的离子搜索栏,我使用的是 (ionChangeEvent.target as HTMLIonInputElement).value as string
为什么需要明确?这太浪费时间了,DOM 事件是我使用 TS 的最大缺点之一,我一直在寻找关于 SO 的 TS 定义。
T
Torsten Barthel

这是我使用的简单方法:

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

TypeScript 编译器显示的错误消失了,代码可以正常工作。


如果您也使用复选框,这是一个很好的解决方案: const value = e.currentTarget.type === 'checkbox' ? (e.currentTarget as HTMLInputElement).checked : e.currentTarget.value
b
belvederef

由于我遇到了两个问题,以稍微不同的方式搜索我的问题,因此我正在复制我的答案,以防你最终来到这里。

在被调用的函数中,您可以使用以下方式定义您的类型:

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

这假设您只对 target 属性感兴趣,这是最常见的情况。如果您需要访问 event 的其他属性,更全面的解决方案涉及使用 & 类型的交集运算符:

event: Event & { target: HTMLInputElement }

您还可以更具体,而不是使用 HTMLInputElement,您可以使用例如 HTMLTextAreaElement 来表示文本区域。


B
BuZZ-dEE

角度 10+

打开 tsconfig.json 并禁用 strictDomEventTypes

  "angularCompilerOptions": {
    ....
    ........
    "strictDomEventTypes": false
  }

禁用严格的规则可能允许编写不正确的代码,这不是一个很好的建议,尤其是随着 Angular 10+ 的进步。
恐怕也不必显式地强制转换类型,尤其是在如此小的/本地范围内。它给出了某种类型安全的外观,但实际上只与禁用严格检查一样好/坏。
这种方法对我有用。投射在 html 中不起作用。这不起作用(keyup)="doFilter(($event.target as HTMLTextAreaElement).value)"
@cklimowski - 对我来说,这是使应用程序在最新版本中以旧版本运行的唯一方法。
C
C. Lewis

就我而言,我有:

const handleOnChange = (e: ChangeEvent) => {
  doSomething(e.target.value);
}

问题是我没有向 ChangeEvent 提供类型参数,以便它知道 e.targetHTMLInputElement。即使我手动告诉它 target 是一个输入元素(例如 const target: HTMLInputElement = e.target),ChangeEvent 仍然不知道这是有道理的。

解决方案是:

// add type argument
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
  doSomething(e.target.value);
}

啊,我已经做了很多次,然后回到这个答案。终于点赞
ChangeEvent 是从哪里导入的?
A
Ali Maher

考虑 $any()

<textarea (keyup)="emitWordCount($any($event))"></textarea>

所有这些解决方案都不适用于 angular 10+,所以请指定 angular 版本。
@Rahi.Shah 我在 Angular 12 上尝试过它,它有效。如果您尝试访问嵌套属性,则需要将对象包装在该属性周围,例如 $any($event.target).value,这会将 event.target 属性标记为 any,您可以访问该值。
@Rahi.Shah 我确实在 Angular 12 中使用了它,但是这个解决方案 stackoverflow.com/a/68106554/11135174 更干净,因为您仍然使用 Typescript 的功能而没有任何“脏修复”。
在 Angular 13 中为我工作。$any($event.target).checked
J
James D

对于那些在 Angular 13 中遇到此错误的人,因为从以前的版本升级

对我来说,问题是我在我的 HTML 中使用了以下内容(之前是允许的)

(keyup)="applyFilter($event.target.value)" 

对此的修复是:

HTML:

(keyup)="applyFilter($event)"

组件 - 在我调用的函数中:

applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    // ... etc....
}

现在我可以像以前一样再次使用 filterValue 来过滤页面中的值


随着 Angular 在打字时变得越来越重,这就是整个线程的答案。所有其他答案均为 N/A。使用控制器中的类型、目标和值发送 Event 工作。
B
Burak Odabaş

这是我使用的另一种简单方法;

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

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

也许像上面这样的东西会有所帮助。根据真实代码进行更改。问题是........ target['value']


P
ParisaN

角 11+

打开 tsconfig.json 并禁用 strictTemplates

 "angularCompilerOptions": {
    ....
    ........
    "strictTemplates": false
  }

工作角度 11
这可能会带来如此多的错误。不要这样做。至少,如果您赶时间,请在 tsconfig.json 中改用 "strictDomEventTypes": false
S
Steven Liekens

不要使用涉及投射事件、事件目标或完全禁用类型检查的其他答案的解决方法。这是不安全的。

相反,您应该从 HTML 元素中“提取”值并将其作为参数传递。

过于简单的例子:

<input #searchBox type="text" (input)="doSearch(searchBox.value)">
doSearch(text: string): void {
}

因此,如果您将其扩展到原始示例,您应该得到:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'text-editor',
  template: `
    <textarea #text (keyup)="emitWordCount(text.value)"></textarea>
  `
})
export class TextEditorComponent {
  @Output() countUpdate = new EventEmitter<number>();

  emitWordCount(text: string) {
    this.countUpdate.emit(
      (text.match(/\S+/g) || []).length);
  }
}

你能详细说明为什么这不“安全”吗?
@RaphaëlBalet 因为强制转换有效地告诉 TypeScript 编译器“不要对这行代码进行严格的类型检查”。一个cast对象只有程序员类型检查,大脑是不可靠的。我提出的解决方案不依赖于强制转换或动态类型。
优秀的解决方案
这似乎是 Angular 现在推荐的方式:angular.io/guide/…
I
Idriss Sakhi

最好的方法是使用模板 => 将 id 添加到您的输入中,然后使用它的值

searchNotary(value: string) {
 // your logic
}

这样,当激活严格验证时,您将永远不会出现 Typescript 错误 => 请参阅 angular Docs


M
Monfa.red

用户 TypeScript 内置实用程序类型 Partial<Type>

在您的模板中

(keyup)="emitWordCount($event.target)"

在您的组件中

 emitWordCount(target: Partial<HTMLTextAreaElement>) {
    this.countUpdate.emit(target.value./*...*/);
  }

非常感谢,工作就像一个魅力。对于 Angular 用户,使用它并且不要忘记启用 "strictDomEventTypes": true。还使用 Partial<HTMLInputElement> 进行输入
m
micronyks

我相信它必须有效,但我无法识别任何方式。其他方法可以是,

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

q
qiAlex

这是指定 event.target 的另一种方法:

从'@angular/core'导入{组件,EventEmitter,输出}; @Component({ selector: 'text-editor', template: `` }) export class TextEditorComponent { @Output() countUpdate = new EventEmitter(); emitWordCount({ target = {} as HTMLTextAreaElement }) { // <- 就在这里 this.countUpdate.emit( // 直接使用它而不使用 `event` (target.value.match(/\S+/g) || [] )。长度); } }


C
Charles Zhao

请改用 currentValue,因为 currentValue 的类型是 EventTarget & HTMLInputElement