我在网站的前端使用 Typescript。
假设我正在为各种用户交互设置一些事件处理程序:
const onClick = (event: PointerEvent) => {
console.log(`You clicked coordinates (${event.clientX},${event.clientY})`);
};
const onKeyUp = (event: KeyboardEvent) => {
console.log(`You entered ${event.key}`);
};
当任何事件发生时,我想首先记录有关该事件的一些通用信息。因此,我创建了一个函数,将我的特定事件处理程序包装在通用事件处理程序中:
type EventHandler<
DispatchedEvent extends Event
> = (event: DispatchedEvent) => void;
function setHandler<
DispatchedEvent extends Event,
Handler extends EventHandler<DispatchedEvent>
>(eventHandler: Handler) {
return (event: DispatchedEvent) => {
console.log(`Detected event of type ${event.constructor.name}`);
eventHandler(event);
};
}
我希望能够像这样设置事件处理程序:
const handleClick = setHandler(onClick);
document.querySelector(`button`)!.addEventListener(`click`, handleClick);
const handleKeyUp = setHandler(onKeyUp);
document.querySelector(`input`)!.addEventListener(`click`, handleKeyUp);
但是,在两次对
setHandler
的调用中,Typescript 抱怨事件不兼容:
Argument of type '(event: PointerEvent) => void' is not assignable to parameter of type 'EventHandler<Event>'.
Types of parameters 'event' and 'event' are incompatible.
Type 'Event' is missing the following properties from type 'PointerEvent': height, isPrimary, pointerId, pointerType, and 33 more.ts(2345)
Argument of type '(event: KeyboardEvent) => void' is not assignable to parameter of type 'EventHandler<Event>'.
Types of parameters 'event' and 'event' are incompatible.
Type 'Event' is missing the following properties from type 'KeyboardEvent': altKey, charCode, code, ctrlKey, and 17 more.ts(2345)
如何编写一个包含特定事件处理程序的通用事件处理程序?
type EventHandler<
DispatchedEvent extends Event
> = (event: DispatchedEvent) => void;
function setHandler<
DispatchedEvent extends Event
>(eventHandler: EventHandler<DispatchedEvent>) {
return (event: DispatchedEvent) => {
console.log(`Detected event of type ${event.constructor.name}`);
eventHandler(event);
};
}
const onClick = (event: MouseEvent) => {
console.log(`You clicked coordinates (${event.clientX},${event.clientY})`);
};
const onKeyUp = (event: KeyboardEvent) => {
console.log(`You entered ${event.key}`);
};
const handleClick = setHandler(onClick);
document.querySelector(`button`)!.addEventListener(`click`, onClick);
const handleKeyUp = setHandler(onKeyUp);
document.querySelector(`input`)!.addEventListener(`keyup`, handleKeyUp);