我写了一个React钩子,通过自动清理将事件侦听器添加到事件目标。实现非常简单,但是类型定义存在问题。
我创建了以下可行的实现。
type Listener<E extends Event = Event> = (event: E) => void;
type Options = boolean | AddEventListenerOptions;
function useEventListener<K extends keyof DocumentEventMap>(
target: Document,
type: K,
listener: Listener<DocumentEventMap[K]>,
options?: Options,
): void;
function useEventListener<T extends HTMLElement, K extends keyof HTMLElementEventMap>(
target: T,
type: K,
listener: Listener<HTMLElementEventMap[K]>,
options?: Options,
): void;
function useEventListener(
target: EventTarget,
type: string,
listener: Listener,
options?: Options,
): void;
function useEventListener(
target: EventTarget,
type: string,
listener: Listener,
options?: Options,
): void {
useEffect(() => {
target.addEventListener(type, listener, options);
return () => target.removeEventListener(type, listener, options);
}, [listener, options, target, type]);
}
function onClick(event: MouseEvent) {}
useEventListener(document, 'click', onClick);
但是,这意味着需要显式添加所有可接受的事件目标。如果可以自动推迟,那就更好了。我尝试了以下方法:
function useEventListener<T extends EventTarget>(
target: T,
type: Parameters<EventTarget['addEventListener']>[0],
listener: Parameters<EventTarget['addEventListener']>[1],
options?: Parameters<EventTarget['addEventListener']>[2]
): void {}
function onClick(event: MouseEvent) {}
useEventListener(document, 'click', onClick);
…但是会引发错误。
我可以从任何类型的事件目标传入的事件目标中延迟事件侦听器类型吗?