Typescript type BeforeInstallPromptEvent
Asked Answered
A

3

23

What's kind of type I should use when using beforeinstallprompt event?

I tried BeforeInstallPromptEvent type, but gave me an error:

export class PwaService {
  //promptEvent: BeforeInstallPromptEvent;
  promptEvent;
  constructor(private swUpdate: SwUpdate, platform: PlatformService) {
    if(platform.isBrowser()){
      swUpdate.available.subscribe(event =>  {
        /*if (askUserToUpdate()) {
          window.location.reload();
        }*/
      });
      window.addEventListener('beforeinstallprompt', event => {
        this.promptEvent = event;
      });
    }
  }

  install(): void {
    if(this.promptEvent){
      this.promptEvent.prompt();
    }
  }
}
Azotobacter answered 24/7, 2018 at 16:44 Comment(1)
I'm reviewing MDN's docs on the BeforeInstallPromptEvent and it doesn't appear to me that the Promise returned by userChoice provides an Object as it's argument. However, Google Developers - Web Fundamentals documents the Type to be as the above describes. If I can find some clarity to the matter I'll be sure to document it.Unpeg
T
46

The BeforeInstallPromptEvent is a non-standard Web API and currently only supported by Chrome and Android. I'm not even sure whether Google considers it stable yet, but in either case I wouldn't expect to see an official type definition in the TypeScript DOM library any time soon.

However you can define the type yourself, e.g. in a .d.ts file. I use the definition below (comments from MDN), which seems to be accurate enough in Chrome 68.

/**
 * The BeforeInstallPromptEvent is fired at the Window.onbeforeinstallprompt handler
 * before a user is prompted to "install" a web site to a home screen on mobile.
 *
 * @deprecated Only supported on Chrome and Android Webview.
 */
interface BeforeInstallPromptEvent extends Event {

  /**
   * Returns an array of DOMString items containing the platforms on which the event was dispatched.
   * This is provided for user agents that want to present a choice of versions to the user such as,
   * for example, "web" or "play" which would allow the user to chose between a web version or
   * an Android version.
   */
  readonly platforms: Array<string>;

  /**
   * Returns a Promise that resolves to a DOMString containing either "accepted" or "dismissed".
   */
  readonly userChoice: Promise<{
    outcome: 'accepted' | 'dismissed',
    platform: string
  }>;

  /**
   * Allows a developer to show the install prompt at a time of their own choosing.
   * This method returns a Promise.
   */
  prompt(): Promise<void>;

}
Tractor answered 14/8, 2018 at 18:1 Comment(3)
Don't forget interface WindowEventMap { "beforeinstallprompt": BeforeInstallPromptEvent; } Might also need to put this in a declare global {} block.Proteinase
Is this still the case?Hatchway
it should not be marked as @deprecated since it is still supported by newest versions of all browsers (except iOS Safari and Firefox)Meteorite
C
19

Improvement to the accepted answer: you also need to add a key into WindowEventMap:

interface BeforeInstallPromptEvent extends Event {
  readonly platforms: string[];
  readonly userChoice: Promise<{
    outcome: "accepted" | "dismissed";
    platform: string;
  }>;
  prompt(): Promise<void>;
}

declare global {
  interface WindowEventMap {
    beforeinstallprompt: BeforeInstallPromptEvent;
  }
}

window.addEventListener("beforeinstallprompt", (e) => {}); // e is now typed

Note the declare global {} is a wrapper for typing global stuff in your code. You could also do it in an ambient file where no import / export keyword exists, then no need for the wrapper. But it's a good practice to put related code in the same file.

Calculable answered 20/4, 2021 at 1:40 Comment(1)
nice improvement. this is necessary if you are using the strictFunctionTypes flagWinkler
A
1

Another addition to the interface could be to extract the userChoice as a type. An promise object of the same shape is also returned by prompt():

type UserChoice = Promise<{
  outcome: 'accepted' | 'dismissed';
  platform: string;
}>;

interface BeforeInstallPromptEvent extends Event {
  readonly platforms: string[];
  readonly userChoice: UserChoice;
  prompt(): Promise<UserChoice>;
}

See: https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent/prompt#return_value

Assault answered 18/1, 2024 at 10:44 Comment(1)
So the user choice is both returned by prompt() and userChoice, only that prompt is a double-wrapped Promise?Kristeenkristel

© 2022 - 2025 — McMap. All rights reserved.