Type guard not being identified when assigned to boolean – strict mode

I have the following code:

The condition is the same in both typeguards, but only the second one works. I’d love to understand why?

export class MessageService {
  private _iframe?: HTMLIFrameElement;

  sendMessage() {
    const appLoaded = !!this._iframe?.contentWindow;

    // why does this not work?
    if (appLoaded) {
        this._iframe.contentWindow.postMessage({}, '*'); // ERROR
    }

    // while this does
    if(!!this._iframe?.contentWindow) {
        this._iframe.contentWindow.postMessage({}, '*');
    }
  }
}

TS Playground link

Thanks!

>Solution :

Because TypeScript’s flow analysis doesn’t go that far. It doesn’t track the fact that appLoaded being true also means that this._iframe?.contentWindow is also truthy. It’s just a pragmatic limitation of the compiler. In theory, it could do it (until/unless you called a function after the assignment and before using contentWindow, at which point this._iframe and or this._iframe.contentWindow may have changed), but doing that is complex enough that it doesn’t.

You could always do something like this, if you want to avoid repeating the condition:

const wnd = this._iframe?.contentWindow;
// ...
if (wnd) {
    wnd.postMessage({}, '*');
}

Leave a Reply