如何让打字稿停止抱怨它不知道的功能?

时间:2014-09-23 11:24:07

标签: javascript typescript

我使用Typescript作为需要使用JavaScript全屏API的网络应用。全屏API尚未得到官方支持,因此您必须使用供应商前缀。这是我的代码,基于MDN的示例:

function toggleFullScreen(element: JQuery) {
    var fs = element[0];
    if (!document.fullscreenElement &&    // alternative standard method
        !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {  // current working methods
        if (fs.requestFullscreen) {
            fs.requestFullscreen();
        } else if (fs.msRequestFullscreen) {
            fs.msRequestFullscreen();
        } else if (fs.mozRequestFullScreen) {
            fs.mozRequestFullScreen();
        } else if (fs.webkitRequestFullscreen) {
            fs.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
        }
    } else {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
    }
}

但是在我的IDE(Visual Studio,但这会发生在任何地方),我得到的错误如下:

The property 'fullscreenElement' does not exist on value of type 'Document'.
The property 'mozFullScreenElement' does not exist on value of type 'Document'.
The property 'webkitFullscreenElement' does not exist on value of type 'Document'.  

当然TypeScript不知道这些函数是否存在,但我也不想将文档重新声明为any只是为了摆脱这些错误,因为那样我就会失去所有其他类型的提示。

这里有什么解决方案?我如何让TypeScript停止抱怨,但保留尽可能多的类型注释?

7 个答案:

答案 0 :(得分:14)

简单地说,您可以将这些项添加到Document界面,错误就会消失。

interface Document {
    exitFullscreen: any;
    mozCancelFullScreen: any;
    webkitExitFullscreen: any;
    fullscreenElement: any;
    mozFullScreenElement: any;
    webkitFullscreenElement: any;
}

你可以为每一个添加完整的类型信息,即使是简单的:

interface Document {
    exitFullscreen: () => void;
    mozCancelFullScreen: () => void;
    webkitExitFullscreen: () => void;
    fullscreenElement: () => void;
    mozFullScreenElement: () => void;
    webkitFullscreenElement: () => void;
}

这可以防止它们被误用。

对于静态属性,您可能只需要使类型动态化,下面示例中的重要部分是Element上的类型断言,即(<any>Element)

fs.webkitRequestFullscreen((<any>Element).ALLOW_KEYBOARD_INPUT);

答案 1 :(得分:10)

我有同样的问题。只需使用方括号&#39;解决它的符号。

 if (document['exitFullscreen']) {
    document['exitFullscreen']();
 } else if (document['webkitExitFullscreen']) {
    document['webkitExitFullscreen']();
 } else if (document['mozCancelFullScreen']) {
    document['mozCancelFullScreen']();
 } else if (document['msExitFullscreen']) {
    document['msExitFullscreen']();
 }

答案 2 :(得分:5)

除了对Fenton的回答外,我们还为这些类型添加了一些细节,并在具有导入/导出功能的常规TypeScript模块中对其进行了声明。这意味着您还必须声明全局名称空间:

declare global {
  interface Document {
    mozCancelFullScreen?: () => Promise<void>;
    msExitFullscreen?: () => Promise<void>;
    webkitExitFullscreen?: () => Promise<void>;
    mozFullScreenElement?: Element;
    msFullscreenElement?: Element;
    webkitFullscreenElement?: Element;
  }

  interface HTMLElement {
    msRequestFullscreen?: () => Promise<void>;
    mozRequestFullscreen?: () => Promise<void>;
    webkitRequestFullscreen?: () => Promise<void>;
  }
}

答案 3 :(得分:2)

Steve fenton的回答非常好,从长远来看,这是你应该做的事情。记住类型是文档,将帮助下一个开发人员。

错误但证明打字稿是允许的,如果你希望它是

纯粹作为一个思想实验,你可以创建一个局部变量来遮蔽全局变量,显式地只将它键入任何一次:

function toggleFullScreen(element: JQuery) {
    var document:any = window.document;
    document.AnythingCanHappen = 123; // No error 
}

对于更多花哨的(从外部范围抓取):

var Element_Copy=Element; 
function toggleFullScreen(element: JQuery) {
    var Element:any = Element_Copy; 
    Element.ShootMyself = true;
} 

完整示例:

var Element_Copy=Element;                         // Magic
function toggleFullScreen(element: JQuery) {
    var document:any = window.document;           // Magic
    var Element:any = Element_Copy;               // Magic
    var fs = element[0];
    if (!document.fullscreenElement &&    // alternative standard method
        !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {  // current working methods
        if (fs.requestFullscreen) {
            fs.requestFullscreen();
        } else if (fs.msRequestFullscreen) {
            fs.msRequestFullscreen();
        } else if (fs.mozRequestFullScreen) {
            fs.mozRequestFullScreen();
        } else if (fs.webkitRequestFullscreen) {
            fs.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
        }
    } else {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
    }
}

答案 4 :(得分:1)

不建议这样做,但是另一种阻止编译器抱怨的解决方案:

const document: any = window.document;

答案 5 :(得分:1)

我今天遇到了同样的问题,在这里看到的解决方案在我们的angular 7项目中并未完全起作用。

这是我们为使其正常运行所做的工作。 如上所述,我们首先为Document创建了一个接口。 (在我们的案例中,我们只需要'fullscreenElement',但是您可以添加任何您喜欢的东西)。

export interface Document extends HTMLDocument {
    fullscreenElement: any;
}

将其导入到我们的组件中而不实现它。

import { Document } from '../interfaces/document';

然后,您可以将document.fullscreenElement强制转换为我们上面创建的扩展类型,而不是使用document,如下所示:

(document as Document).fullscreenElement

这使我们可以像这样制作全屏变化检测器:

@HostListener('document:fullscreenchange', ['$event']) onfullscreenchange(e) {
  if ((document as Document).fullscreenElement) {
    this.isFullscreen = true;
  } else {
    this.isFullscreen = false;
  }
}

Typescript现在将接受这些新定义的属性。

答案 6 :(得分:0)

您可以在访问属性和函数之前将其强制转换为“任意”。

示例:

if ((<any> canvas).mozRequestFullScreen) {
    (<any> canvas).mozRequestFullScreen();
}
相关问题