Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'

I have this custom event setup, and it works with TypeScript 2.5.3, but when I updated to 2.6.1 I get an error

window.addEventListener('OnRewards', (e: CustomEvent) => {     // my code here }) 

[ts] Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.

Type '(e: CustomEvent) => void' is not assignable to type 'EventListenerObject'.

Property 'handleEvent' is missing in type '(e: CustomEvent) => void'.

I am not exactly sure what to do here to fix this.

like image 906
Get Off My Lawn Avatar asked Nov 07 '17 19:11

Get Off My Lawn


1 Answers

This is due to the behavior of the --strictFunctionTypes compiler flag added in TypeScript v2.6. A function of type (e: CustomEvent) => void is no longer considered to be a valid instance of EventListener, which takes an Event parameter, not a CustomEvent.

So one way to fix it is to turn off --strictFunctionTypes.


Another way is to pass in a function that takes an Event and then narrows to CustomEvent via a type guard:

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  }) 

A third way is to use the other overload of addEventListener():

addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void; 

If the type parameter is the name of a known event type (K extends keyof WindowEventMap) like "onclick", then the listener function will expect its parameter to be of that narrowed event type (WindowEventMap[K]). The problem is that "OnRewards" is not a known event type... unless you use declaration merging to make it known:

// merge into WindowEventMap interface WindowEventMap {     OnRewards: CustomEvent } 

Or, if you're inside a module (anything with export in it), use global augmentation:

// merge into WindowEventMap declare global {   interface WindowEventMap {     OnRewards: CustomEvent   } } 

Then use your code as before:

// no error! window.addEventListener('OnRewards', (e: CustomEvent) => {     // my code here }) 

So, those are your options. Which one you want to choose is up to you. Hope that helps; good luck!

like image 89
jcalz Avatar answered Sep 27 '22 19:09

jcalz