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