如何在TypeScript中监听表单元素的回车键按下事件?
问题场景
想要在TypeScript中为表单输入框绑定按键事件,检测用户是否按下回车键,初始编写的代码如下:
const search_field = document.querySelector('#search-field'); search_field?.addEventListener('keypress', (event) => { const target = event.target as HTMLInputElement; if (event.key === 'Enter') { console.log('searching for:'+target.value); } });
编译时触发错误:
TS2339: Property 'key' does not exist on type 'Event'.
尝试将事件类型改为KeyboardEvent后,修改后的代码:
const search_field = document.querySelector('#search-field'); search_field?.addEventListener('keypress', (event:e:KeyboardEvent) => { const target = event.target as HTMLInputElement; if (event.key === 'Enter') { console.log('searching for:'+target.value); } });
又出现新的类型不匹配错误:
TS2769: No overload matches this call.
Overload 1 of 2, '(type: keyof ElementEventMap, listener: (this: Element, ev: Event) => any, options?: boolean | AddEventListenerOptions | undefined): void | undefined', gave the following error.
Argument of type '"keypress"' is not assignable to parameter of type 'keyof ElementEventMap'.
Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void | undefined', gave the following error.
Argument of type '(event: KeyboardEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
Type '(event: KeyboardEvent) => void' is not assignable to type 'EventListener'.
Types of parameters 'event' and 'evt' are incompatible.
Type 'Event' is missing the following properties from type 'KeyboardEvent': altKey, charCode, code, ctrlKey, and 17 more.
正确解决方案
有两种简洁的方式解决该类型问题,同时遵循现代浏览器的事件规范:
方式一:回调内对事件做类型断言
保持事件参数声明为Event,在使用时将其断言为KeyboardEvent,同时替换废弃的keypress为keydown:
const search_field = document.querySelector('#search-field'); search_field?.addEventListener('keydown', (event: Event) => { const keyboardEvent = event as KeyboardEvent; const target = event.target as HTMLInputElement; if (keyboardEvent.key === 'Enter') { console.log('searching for:' + target.value); } });
方式二:明确元素与事件的类型映射
通过泛型指定querySelector的返回类型为HTMLInputElement,同时利用TypeScript的DOM事件类型映射,直接为keydown事件指定KeyboardEvent类型:
const search_field = document.querySelector<HTMLInputElement>('#search-field'); search_field?.addEventListener('keydown', (event: KeyboardEvent) => { if (event.key === 'Enter') { console.log('searching for:' + search_field.value); } });
关键提示
- 优先使用
keydown事件:keypress已被MDN标记为废弃,keydown支持所有按键类型,且在TypeScript的类型系统中映射更准确。 - 明确元素类型:使用
querySelector<HTMLInputElement>()可以直接获取输入框类型,避免后续对event.target的重复类型断言。 - 匹配事件与类型:标准DOM事件类型会自动关联对应的事件对象类型,无需强制指定不匹配的类型导致报错。
内容的提问来源于stack exchange,提问作者Cerin

