This is my code
window.addEventListener('message', (e) => {
e.source.postMessage('hi there, I hear you!', '*');
});
This is the error:
[ts] Cannot invoke an expression whose type lacks a call signature. Type '((message: any, targetOrigin: string, transfer?: any[]) => void) | ((message: any, transfer?: any[]) => void)' has no compatible call signatures.
When I inspect postMessage
it seems to be a method on window
and have the signature:
declare function postMessage(
message: any,
targetOrigin: string,
transfer?: any[]
): void;
That looks very much like my call signature to me. So what is wrong with my code?
e.source
is of type MessageEventSource
.
type MessageEventSource = WindowProxy | MessagePort | ServiceWorker;
Since only WindowProxy
has the method signature you're using, you can guard it with:
window.addEventListener('message', (e) => {
if (!(e.source instanceof MessagePort) && !(e.source instanceof ServiceWorker)) {
e.source.postMessage('hi there, I hear you!', '*');
}
});
Or somehow else tell the TS that your e.source
is of type WindowProxy | Window
.
The previous answer is correct, however you're risking crashing in not-so-old browsers that do not support MessagePort
or ServiceWorker
yet. You could check if MessagePort
and ServiceWorker
exist in the global space using typeof
, but that's not good enough for TypeScript static validator. Also it makes the condition complicated unnecessarily.
As alternative I propose checking against Window, which does exist in all browsers and prevents crashing in not-so-old browsers. Event#source can also be null, so that's also implicit in the new condition. And it's just better.
window.addEventListener('message', (e) => {
if (!(e.source instanceof Window)) return;
// Use normally.
e.source.postMessage('hi there, I hear you!', '*');
});
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