打字稿键盘事件:“事件”类型的参数不可分配给“键盘事件”类型的参数
Posted
技术标签:
【中文标题】打字稿键盘事件:“事件”类型的参数不可分配给“键盘事件”类型的参数【英文标题】:Typescript keyboard event : argument of type 'Event' is not assignable to parameter of type 'KeyboardEvent' 【发布时间】:2018-04-25 23:26:07 【问题描述】:即使代码运行完美,我也有以下错误:
"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'.
有没有办法通过或解决问题?
【问题讨论】:
【参考方案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);
);
);
取决于你的口味。
【讨论】:
【参考方案2】:TypeScript 在这里无法实现完整的飞跃,因为它只知道事件名称将是一个字符串,因此使用最通用的事件类型。
下面的示例转换为一个独立运行的示例 - 所以我已经将一些东西“从课堂上”用于演示......
虽然字符串是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;
//...
在最后一个示例中,我们将数组中元素的类型限制为仅键盘事件名称,因此编译器现在知道它不仅仅处理任何旧字符串,并且可以推断事件类型。
【讨论】:
以上是关于打字稿键盘事件:“事件”类型的参数不可分配给“键盘事件”类型的参数的主要内容,如果未能解决你的问题,请参考以下文章
AWS CDK,打字稿-“this”类型的参数不可分配给“Construct”类型的参数
打字稿:如何键入 Ramda R.prop(key) T' 不可分配给类型为 '(s: ) => 的参数
expressjs:打字稿:“typeof <express.Router>”类型的参数不可分配给“RequestHandlerParams”类型的参数