Typescript: Overriding / extending Lib.d.ts with preexisting identifer

2.6k Views Asked by At

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;
}
2

There are 2 best solutions below

8
Nitzan Tomer On BEST ANSWER

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
0
Mário Meyrelles On

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();
        }
    }
}