我有自定义事件设置,它适用于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)=>中缺少属性'handleEvent'无效”。
我不确定该怎么做才能解决这个问题。
答案 0 :(得分:12)
这是由于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"
不是已知的事件类型...除非您使用declaration merging 使知道它:
// merge into WindowEventMap
interface WindowEventMap {
OnRewards: CustomEvent
}
或者,如果您在模块内(其中包含export
的任何内容),请使用global augmentation:
// merge into WindowEventMap
declare global {
interface WindowEventMap {
OnRewards: CustomEvent
}
}
然后像以前一样使用您的代码:
// no error!
window.addEventListener('OnRewards', (e: CustomEvent) => {
// my code here
})
所以,这些是你的选择。您要选择哪一个取决于您。希望有所帮助;祝你好运!
答案 1 :(得分:4)
建立jcalz's excellent answer,您还可以使用type assertion更清洁:
bitmap
答案 2 :(得分:1)
你也有这个选择:
window.addEventListener('OnRewards', (e: CustomEvent) => {
// your code here
} as (e: Event) => void)
答案 3 :(得分:0)
我根据@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');
}
}
});