如何修复 TypeScript 中 EventTarget 上不存在的属性?
TypeScript 是一种开源语言,它为 JavaScript 提供了可选的静态类型。它允许开发者通过在编译时而不是运行时捕获类型相关的错误,从而编写更易于维护的代码。然而,在 TypeScript 中使用事件监听器可能有点棘手。一个常见问题是"EventTarget 上不存在的属性"错误。当您尝试访问 TypeScript 无法识别的事件目标上的属性时,就会发生此错误。
在本文中,我们将讨论如何修复此错误,并提供示例来演示如何在 TypeScript 中使用事件监听器。
理解错误
在深入研究解决方案之前,必须先了解此错误发生的原因。在 TypeScript 中,EventTarget 接口表示任何可以接收事件的对象,例如窗口或 HTML 元素。但是,并非所有属性和方法都定义在 EventTarget 接口上。例如,假设您尝试在事件监听器中访问 HTML 输入元素的"value"属性。在这种情况下,TypeScript 可能会抛出"属性不存在 EventTarget"错误,因为 EventTarget 接口未定义"value"属性。
要修复此错误,您需要告知 TypeScript 事件目标是一个 HTML 元素,并为该元素提供正确的接口定义。让我们看一些示例来了解如何操作。
示例 1:访问输入元素的 Value 属性
创建一个包含输入字段的表单的 HTML 文件,如下所示 -
index.html
<html lang="en">
<head>
<script src = "test.js"> </script>
</head>
<body>
<form action = "">
<input type = "text">
</form>
</body>
</html>
为了在用户提交表单时捕获输入字段的值,您可以编写如下事件监听器:-
const form = document.querySelector('form');
form!.addEventListener('submit', (event) => {
event.preventDefault();
const inputValue = event!.target!.value;
console.log(inputValue);
});
但是,TypeScript 可能会抛出 "property not existing on EventTarget" 错误,因为 EventTarget 接口上未定义"value"属性。
要修复此错误,您需要告诉 TypeScript 事件目标是 HTMLInputElement。您可以使用类型断言来实现这一点,如下所示 -
test.ts
const form = document.querySelector('form');
form!.addEventListener('submit', (event) => {
event.preventDefault();
const inputValue = (event!.target as HTMLInputElement)!.value;
console.log(inputValue);
});
在此示例中,我们使用 "as" 关键字告诉 TypeScript 事件目标是 HTMLInputElement。现在,TypeScript 知道 EventTarget 上存在 "value" 属性,并且不会抛出错误。
输出

示例 2:使用自定义事件
假设您要定义一个自定义事件并从元素调度该事件。您可以编写如下代码 -
const element = document.querySelector('#my-element');
// 定义自定义事件
const myEvent = new CustomEvent('my-event', {
detail: {
message: 'Hello, world!'
}
});
// 调度事件
element.dispatchEvent(myEvent);
// 处理事件
element!.addEventListener('my-event', (event) => {
const message = (event as CustomEvent).detail.message;
console.log(message);
});
但是,如果您尝试在事件监听器中访问事件的 "detail" 属性,TypeScript 可能会抛出 "property not existing on EventTarget" 错误,因为 "detail" 属性未在 EventTarget 接口上定义。
要修复此错误,您需要告诉 TypeScript 事件目标是 CustomEvent。您可以使用另一种类型的断言来实现这一点,如下所示 -
const element = document.querySelector('#my-element');
// 定义自定义事件
const myEvent = new CustomEvent('my-event', {
detail: {
message: 'Hello, world!'
}
});
// 调度事件
element!.dispatchEvent(myEvent);
// 处理事件
element!.addEventListener('my-event', (event) => {
const message = (event as CustomEvent).detail.message;
console.log(message);
});
在此示例中,我们使用类型断言来告诉 TypeScript 该事件是 CustomEvent。现在,TypeScript 知道事件中存在 "detail" 属性,并且不会抛出错误。
输出

示例 3:使用包含多种事件类型的事件监听器
假设您想监听一个元素上的多种事件类型,例如 "click" 和 "keydown"。您可以编写如下代码 -
const element = document.querySelector("#my-element");
// 处理点击事件
element!.addEventListener("click", (event) => {
console.log("Clicked!");
console.log(`Clicked at (${MouseEvent.clientX}, ${MouseEvent.clientY})`);
});
// 处理键盘按下事件
element!.addEventListener("keydown", (event) => {
console.log("Keydown!");
console.log(`按下的键:${KeyboardEvent.code}`);
});
但是,当您尝试访问事件的属性(例如 "keydown" 事件上的 "keyCode" 属性)时,TypeScript 可能会抛出 "property not existing on EventTarget" 错误,因为 EventTarget 接口未定义这些属性。
要修复此错误,您需要告诉 TypeScript 该事件是特定类型的事件,例如 MouseEvent 或 KeyboardEvent。
您可以通过在每个事件监听器中使用类型断言来实现这一点,如下所示 -
const element = document.querySelector('#my-element');
// 处理点击事件
element.addEventListener('click', (event) => {
const mouseEvent = event as MouseEvent;
console.log(`Clicked at (${mouseEvent.clientX}, ${mouseEvent.clientY})`);
});
// 处理按键事件
element.addEventListener('keydown', (event) => {
const keyboardEvent = event as KeyboardEvent;
console.log(`Key pressed: ${keyboardEvent.code}`);
});
在此示例中,我们使用类型断言来告知 TypeScript,该事件是 MouseEvent 还是 KeyboardEvent,具体取决于事件的类型。通过这样做,TypeScript 可以识别事件的属性和方法,并且不会抛出 "属性不存在于 EventTarget" 错误。
输出

结论
在 TypeScript 中使用事件监听器时,尤其是在监听多种类型的事件时,可能会出现"EventTarget 上不存在属性"的错误。要修复此错误,您需要在每个事件监听器中使用类型断言,告知 TypeScript 该事件是特定类型的事件。
本文提供了三个示例来演示如何修复"EventTarget 上不存在属性"的错误。我们在每个示例中都使用了类型断言来为元素或事件提供正确的接口定义。通过这样做,TypeScript 能够识别事件目标上的属性和方法,并且我们能够编写更易于维护的代码。
请记住要负责任地使用类型断言,并确保代码保持安全和可维护。使用这些技巧,您可以在 TypeScript 中使用事件监听器时编写更健壮、更无错误的代码。

