I'm trying to use an EventSource
with Typescript but cannot type correctly the response when using named events.
I tried
const evtSource = new EventSource('/my-url');
const parseMyEvent = (evt: Event) => {
const data: MyDataInterface = JSON.parse(evt.data);
console.log(data)
}
evtSource.addEventListener('my-event', parseMyEvent);
Fails, because Event
has no property data
const evtSource = new EventSource('/my-url');
const parseMyEvent = (evt: MessageEvent) => {
const data: MyDataInterface = JSON.parse(evt.data);
console.log(data)
}
evtSource.addEventListener('my-event', parseMyEvent);
Fails on evtSource.addEventListener('my-event', parseMyEvent)
, with "No overload matches this call.
".
I know that MessageEvent
is a generic interface, but what should I use as its type?
I'm using TS 3.5.3 so I tried to install the external type @types/eventsource
with no luck too (I know, it is for the polyfill EventSource lib, but I tried)
When using the generic evtSource.onMessage = fn
it works without any problems
It should be possible to type the listener/response of a EventSource event in TS, but how?
The below code should work. Basically, you are using TypeScript's Type assertions and let the compiler trust you that the underlying event is actually an object of type MessageEvent
:
const evtSource = new EventSource('/my-url');
const parseMyEvent = (evt: Event) => {
const messageEvent = (evt as MessageEvent); // <== This line is Important!!
const data: MyDataInterface = JSON.parse(messageEvent.data);
console.log(data)
}
evtSource.addEventListener('my-event', parseMyEvent);
The addEventListener
method on EventSource
has a generic that refers to a type mapping interface (EventSourceEventMap
). As mentioned in the comments. the generic initially only accepts "error" | "message" | "open"
, but that's because those are the only types defined in the map by default. The intent is that you augment the map with your own types for whatever custom events you are adding.
So in your case, what you need is:
declare global {
interface EventSourceEventMap {
['my-event']: MessageEvent<MyDataInterface>;
}
}
With that, typescript will not only know that the message passed to my-event
does have a data
property, it will know the type of that property as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With