你如何在 TypeScript 的 `window` 上显式设置一个新属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12709074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 00:48:24  来源:igfitidea点击:

How do you explicitly set a new property on `window` in TypeScript?

typescript

提问by joshuapoehls

I setup global namespaces for my objects by explicitly setting a property on window.

我通过在 上显式设置属性来为我的对象设置全局命名空间window

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

TypeScript underlines MyNamespaceand complains that:

TypeScript 强调MyNamespace并抱怨:

The property 'MyNamespace' does not exist on value of type 'window' any"

属性 'MyNamespace' 不存在于类型为 'window' any 的值上"

I can make the code work by declaring MyNamespaceas an ambient variable and dropping the windowexplicitness but I don't want to do that.

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

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

How can I keep windowin there and make TypeScript happy?

我怎样才能window留在那里并使 TypeScript 开心?

As a side note I find it especially funny that TypeScript complains since it tells me that windowis of type anywhich by definitely can contain anything.

作为旁注,我发现 TypeScript 抱怨特别有趣,因为它告诉我它window的类型any绝对可以包含任何内容。

回答by joshuapoehls

Just found the answer to this in another StackOverflow question's answer.

刚刚在另一个 StackOverflow 问题的答案中找到了答案

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

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

Basically you need to extend the existing windowinterface to tell it about your new property.

基本上你需要扩展现有的window接口来告诉它你的新属性。

回答by chinupson

To keep it dynamic, just use:

要保持动态,只需使用:

(<any>window).MyNamespace

回答by Evan Larsen

AS OF TYPESCRIPT ^3.4.3 THIS SOLUTION NO LONGER WORKS

从 TYPESCRIPT ^3.4.3 开始,此解决方案不再有效

Or...

或者...

you can just type:

你可以输入:

window['MyNamespace']

and you wont get a compile error and it works the same as typing window.MyNamespace

并且您不会收到编译错误,它的工作方式与键入相同 window.MyNamespace

回答by David Boyd

Using TSX? None of the other answers were working for me.

使用多伦多证券交易所?其他答案都不适合我。

Here's what I did:

这是我所做的:

(window as any).MyNamespace

回答by Blake Mitchell

The accepted answer is what I used to use, but with TypeScript 0.9.* it no longer works. The new definition of the Windowinterface seems to completely replace the built-in definition, instead of augmenting it.

接受的答案是我以前使用的答案,但使用 TypeScript 0.9.* 它不再有效。Window接口的新定义似乎完全取代了内置定义,而不是对其进行了扩充。

I have taken to doing this instead:

我已经开始这样做了:

interface MyWindow extends Window {
    myFunction(): void;
}

declare var window: MyWindow;

UPDATE:With TypeScript 0.9.5 the accepted answer is working again.

更新:使用 TypeScript 0.9.5,接受的答案再次起作用。

回答by onalbi

Global are "evil" :), i think the best way to have also the portability is:

全局是“邪恶的”:),我认为同时具有可移植性的最佳方法是:

First you export the interface: (eg: ./custom.window.ts)

首先导出界面:(例如:./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

Second you import

第二次导入

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

Third cast global var window with CustomWindow

使用 CustomWindow 进行第三次强制转换全局变量窗口

declare let window: CustomWindow;

In this way you don't have also red line in different IDE if you use with existent attributes of window object, so at the end try:

通过这种方式,如果您使用 window 对象的现有属性,则在不同的 IDE 中也不会出现红线,因此最后尝试:

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

Tested with Typescript 2.4.x and newest!

使用 Typescript 2.4.x 和最新版本进行测试!

回答by Lucifer Sam

If you need to extend the windowobject with a custom type that requires the use of importyou can use the following method:

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

window.d.ts

窗口.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

See 'Global Augmentation' in the 'Declaration Merging' section of the Handbook: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

请参阅手册“声明合并”部分中的“全局增强”:https: //www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

回答by Stephen Paul

For those using the Angular CLIit's straightforward:

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

src/polyfills.ts

src/polyfills.ts

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

my-custom-utils.ts

我的自定义utils.ts

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

If you're using IntelliJ, you also needed to change the following setting in the IDE before your new polyfills pick up:

如果您使用的是 IntelliJ,则还需要在新的 polyfill 启动之前更改 IDE 中的以下设置:

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

回答by Dimitar Nikovski

I don't need to do this very often, the only case I have had was when using Redux Devtools with middleware.

我不需要经常这样做,我遇到的唯一情况是将 Redux Devtools 与中间件一起使用。

I simply did:

我只是做了:

const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

Or you could do:

或者你可以这样做:

let myWindow = window as any;

let myWindow = window as any;

and then myWindow.myProp = 'my value';

进而 myWindow.myProp = 'my value';

回答by e-cloud

Most of the other answers are not perfect.

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

  • Some of them just suppress the type inference for shop.
  • Some of the others only cares about global variable as namespace, but not as interface/class
  • 其中一些只是抑制商店的类型推断。
  • 其他一些只关心作为命名空间的全局变量,而不关心作为接口/类

I also encounter the similar problem this morning. I tried so many "solutions" on SO, but none of them produce no type error absolutely and enable triggering type jumping in IDE(webstorm or vscode).

我今天早上也遇到了类似的问题。我在 SO 上尝试了很多“解决方案”,但没有一个绝对不会产生类型错误,并在 IDE(webstorm 或 vscode)中启用触发类型跳转。

Finally, from here

最后,从这里

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

, I find a reasonable solution to attach typings for global variable which acts as interface/class and namespace both.

,我找到了一个合理的解决方案来附加作为接口/类和命名空间的全局变量的类型

Example is below:

示例如下:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Now, the code above merges the typings of namespace MyNamespaceand interface MyNamespaceinto the global variable myNamespace(the property of window).

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