即使代码运行完好,我也会出现以下错误:
"TS2345: Argument of type 'Event' is not assignable to parameter of type 'KeyboardEvent'.
Property 'altKey' is missing in type 'Event'."
// In a Class
public listenTo = (window: Window) => {
['keydown', 'keyup'].forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e); // <- error here
});
});
}
public handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
我尝试将事件类型定义为KeyboardEvent,但是我有以下错误:
window.addEventListener(eventName, (e:KeyboardEvent) => {
this.handleEvent(e); // <- error here
});
TS2345: Argument of type '(event: KeyboardEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
Type '(event: KeyboardEvent) => void' is not assignable to type 'EventListenerObject'.
Property 'handleEvent' is missing in type '(event: KeyboardEvent) => void'.
有没有办法通过或解决问题?
答案 0 :(得分:2)
TypeScript无法在这里实现全面飞跃,因为它只知道事件名称将是一个字符串,因此使用了最常用的事件类型。
下面的例子转换为一个独立的运行示例 - 所以我已经采取了一些东西&#34;一个类&#34;为了演示...
虽然字符串是keydown
和keyup
,但您可以保证类型安全,并取代编译器:
let listenTo = (window: Window) => {
['keydown', 'keyup'].forEach(eventName => {
window.addEventListener(eventName, e => {
handleEvent(<any>e);
});
});
}
let handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
如果将某个其他字符串添加到您的事件名称数组中,这将会失败。
由于专业签名,直接使用字符串时可以使用完全类型安全:
window.addEventListener('keydown', e => {
handleEvent(e); // e is KeyboardEvent
});
因此,您可以更强烈地键入数组以获得正确的类型:
type KeyboardEventNames = 'keydown' | 'keyup';
let listenTo = (window: Window) => {
const eventNames: KeyboardEventNames[] = ['keydown', 'keyup'];
eventNames.forEach(eventName => {
window.addEventListener(eventName, e => {
handleEvent(e);
});
});
}
let handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
在最后一个例子中,我们将数组中的元素类型仅仅重置为键盘事件名称,因此编译器现在知道它不会处理任何旧字符串,并且可以推断出事件类型。
答案 1 :(得分:1)
字符串'keyup'
和'keydown'
是已知的字符串文字类型。但是,代码中的字符串不是用于检查已知字符串文字类型的候选对象,除非它们是const
。只需使您的常数不变:
public listenTo = (window: Window) => {
['keydown' as const, 'keyup' as const].forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e);
});
});
}
或
public listenTo = (window: Window) => {
(['keydown', 'keyup'] as const).forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e);
});
});
}
取决于您的口味。