簡體   English   中英

“(e:CustomEvent)=> void”類型的參數不可分配給“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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM