打字稿:使用预先存在的标识符覆盖/扩展 Lib.d.ts

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

我需要打字稿才能停止抱怨我的代码。它在浏览器中运行良好,但全屏 api 还不是官方的,因此打字稿定义不是最新的。

我打电话给document.documentElement.msRequestFullscreen。这会导致类型错误:

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

在查看 lib.d.ts 后,我发现:

documentElement: HTMLElement;

因此 documentElement 被设置为 HTMLElement 类型。我尝试添加自定义定义来覆盖 documentElement。我的自定义定义:

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

我尝试扩展 Document 的接口,但出现错误

错误是:

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

我的打字稿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;
      }
   }
}

停止打字稿编译错误的正确方法是什么?

更新:我找到了解决方法。我没有尝试覆盖设置为 HTMLElement 类型的 documentElement,而是扩展了 HTMLElement 并添加了缺少的属性。

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


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

您不能覆盖现有接口的现有属性,只能添加新的。

基于 MDN Using fullscreen mode and Element documentation 你需要:

Element.requestFullscreen()

存在于lib.d.tslib.es6.d.ts中。

如果您缺少 msRequestFullscreenmozRequestFullScreen,那么您需要将它们添加到 Element:

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

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

document.documentElement.mozRequestFullScreen(); // no error

我正在使用较新版本的 Typescript,我遇到了同样的问题。

我尝试了上面的解决方案,但没有用 - 似乎我屏蔽了现有界面。

为了能够正确扩展两个接口,我必须使用全局声明:

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


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

这样做,我能够正确编译和使用如下代码:

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