我正在尝试将事件侦听器添加到存储在该类的方法中的类内的输入元素中,该方法接受包含eventName
和callback
的props对象。
public setTextFieldInputListener({ eventName, callback }: TextFieldListenerProps): void {
this.input.addEventListener(eventName, callback);
}
此侦听器道具对象是两个接口的并集类型BlurTextFieldCallbackProps
InputTextFieldCallbackProps
export type TextFieldListenerProps = BlurTextFieldListenerProps | InputTextFieldListenerProps;
export interface BaseTextFieldListenerProps {
eventName: Extract<keyof GlobalEventHandlersEventMap, 'blur' | 'input'>;
callback(e?: FocusEvent | Event): void;
}
export interface BlurTextFieldListenerProps extends BaseTextFieldListenerProps {
eventName: Extract<keyof GlobalEventHandlersEventMap, 'blur'>;
callback(e?: FocusEvent): void;
}
export interface InputTextFieldListenerProps extends BaseTextFieldListenerProps {
eventName: Extract<keyof GlobalEventHandlersEventMap, 'input'>;
callback(e?: Event): void;
}
然后,当我尝试分配此eventName
和callback
时,我会得到以下错误:
TS2769:没有与此调用匹配的重载。重载1/2,'(类型:"input"|"blur",listener:(this:HTMLInputElement,ev:Event|FocusEvent(=>有,选项?:boolean | AddEventListenerOptions | undefined(:void,给出以下错误。类型为"的参数(((e?:InputEvent|undefined(=>void(|((e?:FocusEvent|undefined(=>void('不可分配给类型为'的参数(this:HTMLInputElement,ev:Event|FocusEvent(=>任何。。。
一开始,我想知道如果eventName
将是'blur'
,而事件将是FocusEvent
,这可能是一个问题,所以我创建了一个typeguard:
export function isBlurTextFieldProps(value: BaseTextFieldListenerProps): value is BlurTextFieldListenerProps {
return value.eventName === 'blur';
}
我改变了负责设置eventListener的方法:
public setTextFieldInputListener(listenerProps: TextFieldListenerProps): void {
if (isBlurTextFieldProps(listenerProps)) {
this.input.addEventListener(listenerProps.eventName, listenerProps.callback);
}
}
但这根本没有帮助:/
我的问题是:
- 为什么会出现此错误
- 如何在保持强类型的情况下修复它?(我知道我可以用
any
解决这个问题,但我不想用any
(
您可以通过使用通用的<K>addEventListener
方法来实现这一点。K表示事件名称的类型('blur'
、'input'
(。
public setTextFieldInputListener(listenerProps: TextFieldListenerProps): void {
if (isOnBlurTextFieldProps(listenerProps)) {
this.input.addEventListener<'blur'>(listenerProps.eventName, listenerProps.callback.bind(this));
} else if (isOnInputTextFieldProps(listenerProps)) {
this.input.addEventListener<'input'>(listenerProps.eventName, listenerProps.callback.bind(this));
}
}