1

I need to get typescript to stop complaining about my code. It runs fine in the browser but fullscreen api are not official yet so typescript definitions aren't up to date.

I am calling document.documentElement.msRequestFullscreen. This causes type error:

Property 'msRequestFullscreen' does not exist on type 'HTMLElement'.

Upon looking at lib.d.ts, I find this:

documentElement: HTMLElement;

So documentElement is set to type HTMLElement. I tried adding a custom definition to override documentElement. My Custom definition:

// Extend Document Typings
interface Document {
   msExitFullscreen: any;
   mozCancelFullScreen: any;
   documentElement: {
      msRequestFullscreen: any;
      mozRequestFullScreen: any;
   }
}

I tried extending the interface for Document but it gives error

Error is:

lib.d.ts:5704:5 
Duplicate identifier 'documentElement'.

My typescript class

export class ToggleFullScreen {
   viewFullScreenTriggerID: string;
   viewFullScreenClass: string;
   cancelFullScreenClass: string;
   viewFullscreenElem: any;
   activeIcon: string;
   notFullscreenIcon: string;
   isFullscreenIcon: string


   constructor() {
      this.viewFullScreenTriggerID = "#fullScreenTrigger";
      this.viewFullScreenClass = "not-fullscreen";
      this.cancelFullScreenClass = "is-fullscreen";
      this.notFullscreenIcon = "/assets/icon/fullscreen-enter.svg";
      this.isFullscreenIcon = "/assets/icon/fullscreen-exit.svg";
      this.activeIcon = this.notFullscreenIcon;
   }

   toggleFullScreen() {
      this.viewFullscreenElem = document.querySelector(this.viewFullScreenTriggerID);

      if (this.viewFullscreenElem.classList.contains(this.viewFullScreenClass)) {

         var docElm = document.documentElement;
         if (docElm.requestFullscreen) {
            docElm.requestFullscreen();
         } else if (docElm.msRequestFullscreen) {
            docElm.msRequestFullscreen();
         } else if (docElm.mozRequestFullScreen) {
            docElm.mozRequestFullScreen();
         } else if (docElm.webkitRequestFullScreen) {
            docElm.webkitRequestFullScreen();
         }

         this.viewFullscreenElem.classList.toggle(this.viewFullScreenClass);
         this.viewFullscreenElem.classList.toggle(this.cancelFullScreenClass);
         this.activeIcon = this.isFullscreenIcon;

      }

      else if (this.viewFullscreenElem.classList.contains(this.cancelFullScreenClass)) {
         if (document.exitFullscreen) {
            document.exitFullscreen();
         } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
         } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
         } else if (document.webkitCancelFullScreen) {
            document.webkitCancelFullScreen();
         }

         this.viewFullscreenElem.classList.toggle(this.viewFullScreenClass);
         this.viewFullscreenElem.classList.toggle(this.cancelFullScreenClass);
         this.activeIcon = this.notFullscreenIcon;
      }
   }
}

What is the proper way to get typescript compile errors to stop?

UPDATE: I found a workaround. Instead of trying to override documentElement, which is set to type HTMLElement, I extended HTMLElement and added the properties which were missing.

// Extend Document Typings
interface Document {
   msExitFullscreen: any;
   mozCancelFullScreen: any;
}


interface HTMLElement {
   msRequestFullscreen(): void;
   mozRequestFullScreen(): void;
}
TetraDev
  • 16,074
  • 6
  • 60
  • 61

2 Answers2

2

I'm using newer version of Typescript and I faced the same problem.

I tried the solution above and it didn't work - it seemed that I was masking the existing interface.

To be able to extend correctly both interfaces, I had to use a declare global:

declare global {
    interface Document {
        msExitFullscreen: any;
        mozCancelFullScreen: any;
    }


    interface HTMLElement {
        msRequestFullscreen: any;
        mozRequestFullScreen: any;
    }
}

Doing so, I was able to correctly compile and use code like this:

fullScreenClick(e): any {
    var element = document.documentElement;
    if (!$('body').hasClass("full-screen")) {
        $('body').addClass("full-screen");
        $('#fullscreen-toggler').addClass("active");
        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.mozRequestFullScreen()) {
            element.mozRequestFullScreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        }
    } else {
        $('body').removeClass("full-screen");
        $('#fullscreen-toggler').removeClass("active");
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
    }
}
Mário Meyrelles
  • 1,594
  • 21
  • 26
0

You can't override existing properties of an existing interface, only add new ones.

Based on the MDN Using fullscreen mode and Element documentation you need to have:

Element.requestFullscreen()

Which exists in the lib.d.ts and lib.es6.d.ts.

If you're missing msRequestFullscreen and mozRequestFullScreen then you need to add them to Element:

interface Document {
    msExitFullscreen: any;
    mozCancelFullScreen: any;
}

interface Element {
    msRequestFullscreen(): void;
    mozRequestFullScreen(): void;
}

document.documentElement.mozRequestFullScreen(); // no error
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • Thanks, I just figured that out right when you posted. Actually it seems to require that I use `document.documentElement.requestFullscreen` but your answer still is helpful for solving the original question about types interfaces. – TetraDev Jul 13 '16 at 21:54
  • Yeah, I see now that you updated your answer. Just be sure to add the methods to `Element` and not to `HTMLElement`. – Nitzan Tomer Jul 13 '16 at 21:58
  • Will do, just curious why should it be `Element` instead of `HTMLElement` if the type definition i'm extending is originally `documentElement: HTMLElement`? It seems to compile if I use either one. – TetraDev Jul 13 '16 at 22:02
  • 1
    It's true that `documentElement` is of type `HTMLElement`, but in turn, `HTMLElement` extends `Element`. All of those `requestFullscreen` methods (that do exist) are in `Element`. – Nitzan Tomer Jul 13 '16 at 22:06
  • Oh, got ya, Thanks that makes sense. – TetraDev Jul 13 '16 at 22:19
  • One more thing: even though typescript compiler does not complain now, the inline intellisense doesn't recognize the property and gives red squiggly underline on `docElm.msRequestFullscreen` and `docElm.mozRequestFullScreen` saying `Unresolved variable`. Is there a way to get it to see those properties in the new `Element` interface we set up? See: http://screencast.com/t/BzTRyrWelV – TetraDev Jul 13 '16 at 22:27
  • I'm not sure, it works for me in WebStorm. Seems like your IDE fails to take into account the override you've made to `Element`. – Nitzan Tomer Jul 13 '16 at 22:36
  • Got it working, I had to do `interface HTMLElement` for it to detect changes. I'm using IntelliJ IDEA. Thanks for your help. – TetraDev Jul 14 '16 at 15:16