TypeScript泛型绑定DocumentEventMap类型推断报错解决方案
问题根源
泛型定义T = keyof DocumentEventMap仅为T设置了默认类型,没有添加类型约束,TypeScript不会校验T必须是keyof DocumentEventMap的子类型,会出现T被推导为超集、无法作为DocumentEventMap合法索引的报错。
修复后完整代码
import { useEffect } from "react"; // 通过extends关键字添加泛型约束,强制T必须是DocumentEventMap的合法事件名 export function useDocumentListener<T extends keyof DocumentEventMap>( listener: (event: DocumentEventMap[T]) => void, { eventType, key, capture = false, }: { eventType: T; key?: string; capture?: boolean; } ) { useEffect(() => { // 类型断言适配DOM原生addEventListener的重载签名 const eventHandler = listener as EventListener; document.addEventListener(eventType, eventHandler, { capture }); return () => document.removeEventListener(eventType, eventHandler, { capture }); }, [listener, key, eventType, capture]); } // 调用示例:event会自动推导为KeyboardEvent类型 useDocumentListener((event) => { console.log(event.key); }, {eventType: "keydown"});
关键修改点说明
- 核心调整是将泛型写法从
T = keyof DocumentEventMap改为T extends keyof DocumentEventMap,从类型层面限制T只能是DocumentEventMap中存在的合法事件名,从根源解决索引类型不兼容的报错 - 对传入的listener添加
as EventListener类型断言,适配DOM原生addEventListener的内置重载类型定义,避免出现函数参数类型不兼容的额外报错 - 原有参数顺序不需要调整,TypeScript可以根据传入配置项中
eventType的字面量值正确推导泛型T的具体类型,实现事件回调参数的自动类型推断
内容的提问来源于stack exchange,提问作者Omer Demirkan
相关产品推荐
相关产品推荐

