[英]Argument of type '(event: string) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject
[英]Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'
我有这个自定义事件设置,它适用于 TypeScript 2.5.3
,但是当我更新到2.6.1
时出现错误
window.addEventListener('OnRewards', (e: CustomEvent) => {
// my code here
})
[ts]“(e:CustomEvent)=> void”类型的参数不可分配给“EventListenerOrEventListenerObject”类型的参数。
类型“(e:CustomEvent)=> void”不可分配给类型“EventListenerObject”。
类型“(e:CustomEvent)=> void”中缺少属性“handleEvent”。
我不确定要在这里做什么来解决这个问题。
这是由于 TypeScript v2.6 中添加的--strictFunctionTypes
编译器标志的行为。 (e: CustomEvent) => void
类型的函数不再被视为EventListener
的有效实例,它采用Event
参数,而不是CustomEvent
。
所以解决它的一种方法是关闭--strictFunctionTypes
。
另一种方法是传入一个函数,该函数接受一个Event
,然后通过类型保护缩小到CustomEvent
:
function isCustomEvent(event: Event): event is CustomEvent {
return 'detail' in event;
}
window.addEventListener('OnRewards', (e: Event) => {
if (!isCustomEvent(e))
throw new Error('not a custom event');
// e is now narrowed to CustomEvent ...
// my code here
})
第三种方法是使用addEventListener()
的另一个重载:
addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;
如果type
参数是已知事件类型的名称( K extends keyof WindowEventMap
),例如"onclick"
,那么listener
器函数将期望其参数是那个缩小的事件类型( WindowEventMap[K]
)。 问题是"OnRewards"
不是已知的事件类型......除非您使用声明合并来使其为人所知:
// merge into WindowEventMap
interface WindowEventMap {
OnRewards: CustomEvent
}
或者,如果您在一个模块内(其中有任何export
),请使用全局扩充:
// merge into WindowEventMap
declare global {
interface WindowEventMap {
OnRewards: CustomEvent
}
}
然后像以前一样使用您的代码:
// no error!
window.addEventListener('OnRewards', (e: CustomEvent) => {
// my code here
})
所以,这些是你的选择。 你想选择哪一个取决于你。 希望有帮助; 祝你好运!
在jcalz 的优秀答案的基础上,您还可以使用类型断言来更简洁:
window.addEventListener('OnRewards', (e: Event) => {
const detail = (<CustomEvent>e).detail;
...
});
你也有这个选项:
window.addEventListener('OnRewards', (e: CustomEvent) => {
// your code here
} as (e: Event) => void)
我根据@jcalz 的回答创建了一个通用函数
/**
* Checks whether an object can be safely cast to its child type
* @param parent the object to be 'narrowly' cast down to its child type
* @param checkForProps props which aught to be present on the child type
*/
export function isSubTypeWithProps<P, C extends P>(parent: P, ...checkForProps: (keyof C)[]): parent is C {
return checkForProps.every(prop => prop in parent);
}
/**
* Usage example
*/
const el = document.getElementById('test');
el.addEventListener('click', (e: Event) => {
if (isSubTypeWithProps<Event, MouseEvent>(e, 'which')) {
if (e.which === 1) { // primary mouse button only ('which' prop is only available on MouseEvent)
console.log('clicked');
}
}
});
正如 Yukulélé 对 jcalz 的回答所评论的那样,您还可以检查CustomEvent
是否是Event
的实例。
像下面这个例子:
window.dispatchEvent(
new CustomEvent('customEventName', {
detail: { something: true },
})
);
window.addEventListener('customEventName', (e: Event) => {
if (e instanceof CustomEvent) {
if (e?.detail?.something) {
// do something
}
}
});
是的,另一种满足编译器的方法是转换事件对象,例如yourFuctionName(e: Event){ const event = e as CustomEvent <SegmentChangeEventDetail>; console.log(event.detail)}
yourFuctionName(e: Event){ const event = e as CustomEvent <SegmentChangeEventDetail>; console.log(event.detail)}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.