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

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

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

其他回答

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

全球增长

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

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

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

要保持动态,只需使用:

(<any>window).MyNamespace

注意,这可能不适用于TSX,因为编译器可能认为<any>是TSX元素。查看与TSX兼容的类型断言的答案。

对于那些使用Angular CLI的人来说,这很简单:

文件src / polyfills.ts

declare global {
  interface Window {
    myCustomFn: () => void;
  }
}

文件my-custom-utils.ts

window.myCustomFn = function () {
  ...
};

如果你正在使用IntelliJ IDEA,你还需要在IDE中更改以下设置,然后你的新腻子才会开始:

> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.

其他大多数答案都不完美。

其中一些只是为了显示而抑制了类型推断。 其他一些只关心全局变量作为名称空间,而不关心接口/类

今天早上我也遇到了一个类似的问题。我在Stack Overflow上尝试了很多“解决方案”,但没有一个完全没有类型错误,并在IDE中启用触发类型跳转(WebStorm或Visual Studio Code)。

最后,从允许模块定义声明为全局变量#3180

我找到了一个合理的解决方案,为同时充当接口/类和名称空间的全局变量附加类型。

例子如下:

// typings.d.ts
declare interface Window {
    myNamespace?: MyNamespace & typeof MyNamespace
}

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

上面的代码将命名空间MyNamespace和接口MyNamespace的类型合并到全局变量MyNamespace (window的属性)中。

首先,您需要在当前 范围。因为TypeScript想知道对象的类型 对象。由于窗口对象是在其他地方定义的,所以不能重新定义它。

但你可以按以下方式申报:

declare var window: any;

这将不会重新定义窗口对象,也不会创建另一个名为window的变量。这意味着窗口是在其他地方定义的,您只是在当前作用域中引用它。

然后你可以通过以下方式引用你的MyNamespace对象:

window.MyNamespace

或者你可以在窗口对象上简单地设置新属性:

window.MyNamespace = MyObject

现在TypeScript不会抱怨了。