这是我的代码
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.
这很像我的电话签名。那么我的代码有什么问题呢?
答案 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)
上一个答案是正确的,但是您可能会在不支持 MessagePort
或 ServiceWorker
的不太旧的浏览器中崩溃。您可以使用 MessagePort
检查全局空间中是否存在 ServiceWorker
和 typeof
,但这对于 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!', '*');
});