简体   繁体   English

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

[英]How do I get typescript to stop complaining about functions it doesn't know about?

I'm using Typescript for a web app that needs to use the JavaScript full screen API.我正在将 Typescript 用于需要使用 JavaScript 全屏 API 的 Web 应用程序。 The full screen API isn't officially supported yet, so you have to use vendor prefixes.全屏 API 尚未得到官方支持,因此您必须使用供应商前缀。 Here's my code, based on the sample from MDN :这是我的代码,基于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();
        }
    }
}

However in my IDE (Visual Studio, but this would happen anywhere), I get errors like:但是在我的 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'.  

Of course TypeScript can't know that these functions exist, but nor do I want to re-declare document as any just to get rid of these errors, because then I'll lose all the other type hints.当然打字稿无法知道这些功能的存在,但我也不希望重新申报文件作为any只是为了摆脱这些错误的,因为那时我会失去所有其他类型的提示。

What is the solution here?这里的解决方案是什么? How do I get TypeScript to stop complaining but keep as many type annotations as I can?如何让 TypeScript 停止抱怨但尽可能多地保留类型注释?

I have the same problem.我也有同样的问题。 Just use 'Square bracket' notation to solve it.只需使用“方括号”符号来解决它。

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

Simplistically, you could add those items to the Document interface and the errors would go away.简单地说,您可以将这些项目添加到Document界面,错误就会消失。

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

You could add full type information for each of these, even the simple:您可以为每一个添加完整的类型信息,即使是简单的:

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

This would prevent them being mis-used.这将防止它们被误用。

For static properties, you may just need to make the type dynamic, the important part in the example below is the type assertion on Element , ie (<any>Element) :对于静态属性,您可能只需要使类型动态化,下面示例中的重要部分是对Element的类型断言,即(<any>Element)

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

Adding to the answer of Fenton we added some details to these types and declared them in a regular TypeScript Module with imports/exports.除了Fenton的回答之外,我们还为这些类型添加了一些细节,并在带有导入/导出的常规 TypeScript 模块中声明了它们。 This means you also have to declare the global namespace:这意味着您还必须声明全局命名空间:

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

Steve fenton's answer is excellent and in the long run that is what you should do.史蒂夫芬顿的回答非常好,从长远来看,这是你应该做的。 Remember Types are documentation and will help the next developer.记住类型是文档,将帮助下一个开发人员。

Bad but proving that typescript is permissive if you want it to be不好但证明打字稿是允许的,如果你想要的话

Purely as a thought experiment you can create a local variable to shadow the global one and explicitly type it to be any only once:纯粹作为一个思想实验,您可以创建一个局部变量来隐藏全局变量,并将其明确键入为any一次:

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

And for more fancy ones (grab from an outer scope):对于更花哨的(从外部范围抓取):

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

Complete example:完整示例:

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

不推荐这样做,而是阻止编译器抱怨的另一种解决方案:

const document: any = window.document;

I ran into the same problem today and the solutions that I've seen here did not completely work on our angular 7 project.我今天遇到了同样的问题,我在这里看到的解决方案并没有完全适用于我们的 angular 7 项目。

Here is what we've done to make it work.这是我们为使其工作所做的工作。 We've first created an interface for Document as mentioned above.如上所述,我们首先为 Document 创建了一个接口。 (we only needed 'fullscreenElement' in our case, but you can add any you like). (在我们的例子中,我们只需要 'fullscreenElement',但你可以添加任何你喜欢的元素)。

export interface Document extends HTMLDocument {
    fullscreenElement: any;
}

Imported this into our component without implementing it.将其导入到我们的组件中而不实施它。

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

Then, instead of using document.fullscreenElement you can cast document to the expanded type we created above, like this:然后,您可以将document转换为我们上面创建的扩展类型,而不是使用document.fullscreenElement ,如下所示:

(document as Document).fullscreenElement

This allowed us to make a fullscreen change detector like this:这使我们能够制作一个全屏变化检测器,如下所示:

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

Typescript will now accept these newly defined properties. Typescript 现在将接受这些新定义的属性。

You can just cast to "any" before accessing the properties and functions.您可以在访问属性和函数之前强制转换为“any”。

Example:例子:

if ((<any> canvas).mozRequestFullScreen) {
    (<any> canvas).mozRequestFullScreen();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM