我通过显式设置窗口上的属性为我的对象设置全局名称空间。

window.MyNamespace = window.MyNamespace || {};

TypeScript强调MyNamespace,并抱怨:

属性“MyNamespace”在类型为“window”的值上不存在 任何“

我可以通过将MyNamespace声明为环境变量并删除窗口显式来使代码工作,但我不想这样做。

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

我如何保持窗口在那里,让TypeScript满意?

作为旁注,我发现特别有趣的是,TypeScript抱怨,因为它告诉我,窗口的类型是any,它肯定可以包含任何东西。


当前回答

我刚刚在另一个Stack Overflow问题的答案中找到了这个问题的答案。

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

基本上,您需要扩展现有的窗口界面来告诉它您的新属性。

其他回答

如果你使用的是TypeScript 3。X,你可以在其他答案中省略声明全局部分,而只是使用:

interface Window {
  someValue: string
  another: boolean
}

当我使用TypeScript 3.3、Webpack和TSLint时,这种方法很有效。

在四处寻找答案后,我认为这个页面可能会有所帮助:

全球增长

我不确定声明合并的历史,但它解释了为什么下面可以工作。

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

我刚刚在另一个Stack Overflow问题的答案中找到了这个问题的答案。

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

基本上,您需要扩展现有的窗口界面来告诉它您的新属性。

全局变量是“邪恶的”:)我认为拥有可移植性的最好方法是:

首先导出接口:(例如,./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

第二,导入

import {CustomWindow} from './custom.window.ts';

第三,使用CustomWindow强制转换全局变量窗口:

declare let window: CustomWindow;

通过这种方式,你也不会在不同的IDE中有红线,如果你使用它与窗口对象的存在属性,所以在最后尝试:

window.customAttribute = 'works';
window.location.href = '/works';

用TypeScript 2.4测试。X和最新!

如果您需要使用需要使用import的自定义类型来扩展窗口对象,您可以使用以下方法:

window.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

请参阅手册的“声明合并”部分中的全局增强。