![](/img/trans.png)
[英]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.