我尝试将Messagepost返回源时,Typescript抱怨

时间:2018-10-30 12:36:11

标签: typescript

这是我的代码

create(options) {
    /* inserting markup here */
    this.changeDetectorRef.detectChanges();
    options.eventBindings.forEach(([selector, event, listener]) => {
        const element = this.elementRef.nativeElement.querySelector(selector)
        if(element) { 
            element.addEventListener(event, listener); 
        }
    }
}

这是错误

window.addEventListener('message', (e) => {
  e.source.postMessage('hi there, I hear you!', '*');
});

当我检查postMessage时,它似乎是窗口上的一种方法,并且具有签名:

[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.

这很像我的电话签名。那么我的代码有什么问题呢?

2 个答案:

答案 0 :(得分:2)

e.source的类型为MessageEventSource

type MessageEventSource = WindowProxy | MessagePort | ServiceWorker;

由于只有WindowProxy具有您正在使用的方法签名,因此可以使用以下方法进行保护:

window.addEventListener('message', (e) => {
  if (!(e.source instanceof MessagePort) && !(e.source instanceof ServiceWorker)) {
    e.source.postMessage('hi there, I hear you!', '*');
  }
});

或者以其他方式告诉TS您的e.source类型为WindowProxy | Window

答案 1 :(得分:0)

上一个答案是正确的,但是您可能会在不支持 MessagePortServiceWorker 的不太旧的浏览器中崩溃。您可以使用 MessagePort 检查全局空间中是否存在 ServiceWorkertypeof,但这对于 TypeScript 静态验证器来说还不够好。也使条件不必要地复杂化。

作为替代方案,我建议检查 Window,它确实存在于所有浏览器中并防止在不太老的浏览器中崩溃。 Event#source 也可以为 null,因此这也隐含在新条件中。而且效果更好。

window.addEventListener('message', (e) => {
  if (!(e.source instanceof Window)) return;

  // Use normally.
  e.source.postMessage('hi there, I hear you!', '*');
});