首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >强类型事件侦听器函数

强类型事件侦听器函数
EN

Stack Overflow用户
提问于 2022-05-24 14:56:51
回答 1查看 559关注 0票数 2

我正在尝试构建一个函数来添加一个事件侦听器,该监听器使用提供的事件名称来检查提供的处理程序函数是否处理正确的事件。考虑下面的代码片段。

(上下文:这是针对React钩子的,但问题是这样删除了React特定代码的类型记录类型。)

代码语言:javascript
运行
复制
type Events = HTMLElementEventMap & WindowEventMap & DocumentEventMap;
type EventKey = keyof Events;
type ListenerElements = HTMLElement | Window | Document;

const useEventListener = <K extends EventKey>(
  event: K,
  handler: (event: Events[K]) => void,
  element: ListenerElements = window
) => {
  element.addEventListener(event, handler); // <-- Error
};

export default useEventListener;

TS游乐场链接

用法类似于:

代码语言:javascript
运行
复制
const exampleHandler = (event: MouseEvent) => console.log(event);
useEventListener("click", exampleHandler); // Correct

const exampleErroneusHandler = (event: KeyboardEvent) => console.log(event);
useEventListener("click", exampleErroneusHandler); // Error

上面的片段提供了以下错误:

类型‘(事件: EventsK) => void’的参数不能分配给'EventListenerOrEventListenerObject‘类型的参数。类型‘(事件: EventsK) => void’不能分配到键入'EventListener‘。参数'event‘和'evt’的类型是不兼容的。输入'EventsK‘不能分配’EventsK‘。输入“Event”不能键入'Event & ClipboardEvent & UIEvent & AnimationEvent & MouseEvent & InputEvent & FocusEvent & 21 more .& StorageEvent‘。属性“clipboardData”在“事件”类型中缺失,但在“剪贴板事件”类型中是必需的。(2345)

一个修复方法是使用一个不太特定的事件,而不是EventsK。

代码语言:javascript
运行
复制
handler: (event: Event) => void,

是否有一种方法可以实现这一点而不求助于不太具体的事件类型?

(标题相当笨拙,可能会做得更好)

EN

Stack Overflow用户

发布于 2022-05-24 20:45:36

基本上,您的类型检查有效,只需将处理程序转换为EventListener即可。exampleErroneusHandler处理KeyboardEvent。而对类型的验证只允许MouseEvent处理程序作为click处理程序,而click处理程序只能接受MouseEvent处理程序。

我明白吗,您想要对EventMaps的密钥进行验证吗?作为你目前的设置,完全按照你的要求去做。我认为你应该把这个问题改为build a generic function which validates if the event name is allowed for a given event handler

这解决了你的问题

代码语言:javascript
运行
复制
type Events = HTMLElementEventMap & WindowEventMap & DocumentEventMap;
type ListenerElements = HTMLElement | Window | Document;

function useEventListener<E extends Events[keyof Events]>(
  event: keyof Pick<Events, {[K in keyof Events]: Events[K] extends E ? K : never}[keyof Events]>,
  handler: (event: E) => void,
  element: ListenerElements = window
) {
  element.addEventListener(event, handler as EventListener);
};

const exampleHandler = (event: MouseEvent) => console.log(event);
useEventListener("click", exampleHandler); // Correct

const exampleErroneusHandler = (event: KeyboardEvent) => console.log(event);
useEventListener("click", exampleErroneusHandler); // Argument of type '"click"' is not assignable to parameter of type '"keydown" | "keypress" | "keyup"'.ts(2345)

使用以下资源TypeScript基本要素:条件过滤类型

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72365139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档