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

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

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

TypeScript强调MyNamespace并抱怨:

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

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

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

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

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

樱小胖Mandy2020/05/26 09:48:17

首先,您需要在当前范围内声明窗口对象。
因为 TypeScript想知道对象的类型。
由于窗口对象是在其他位置定义的,因此无法重新定义它。
但是您可以声明如下:

declare var window: any;

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

然后,您可以通过以下方式简单地引用MyNamespace对象:

window.MyNamespace

或者,您可以window通过以下方法简单地对象上设置新属性

window.MyNamespace = MyObject

现在 TypeScript将不会抱怨。

米亚2020/05/26 09:48:16

通过使用create-react-app v3.3,我发现实现此目的的最简单方法是扩展Window自动生成类型react-app-env.d.ts

interface Window {
    MyNamespace: any;
}
Elena2020/05/26 09:48:16

我今天想在Angular(6)库中使用它,花了我一段时间才能使它按预期工作。

为了使我的库使用声明,我必须对d.ts文件使用扩展名,以声明全局对象的新属性。

所以最后,该文件最终显示为:

/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts

创建完成后,请不要忘记在您的中公开它public_api.ts

对我来说就做到了。希望这可以帮助。

Chloe2020/05/26 09:48:16

创建一个自定义界面扩展Window并将您的自定义属性添加为可选属性。

然后,让customWindow使用自定义界面,但与原始窗口一起使用。

它与typescript@3.1.3一起使用。

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 
伽罗理查德2020/05/26 09:48:16

供参考(这是正确的答案):

.d.ts定义文件中

type MyGlobalFunctionType = (name: string) => void

如果您在浏览器中工作,则可以通过重新打开Window的界面将成员添加到浏览器的window上下文中:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

NodeJS的想法相同:

declare module NodeJS {
  interface Global {
    myGlobalFunction: MyGlobalFunctionType
  }
}

现在,您声明根变量(实际上将存在于window或global上)

declare const myGlobalFunction: MyGlobalFunctionType;

然后,在一个常规.ts文件中(但作为副作用导入),您实际上实现了它:

global/* or window */.myGlobalFunction = function (name: string) {
  console.log("Hey !", name);
};

最后,通过以下任一方式在代码库中的其他地方使用它:

global/* or window */.myGlobalFunction("Kevin");

myGlobalFunction("Kevin");
猴子2020/05/26 09:48:16

如果您使用的是TypeScript定义管理器,请执行以下操作

npm install typings --global

创建typings/custom/window.d.ts

interface Window {
  MyNamespace: any;
}

declare var window: Window;

安装您的自定义键入:

typings install file:typings/custom/window.d.ts --save --global

完成,使用它‌! TypeScript不会再抱怨了:

window.MyNamespace = window.MyNamespace || {};
番长猴子2020/05/26 09:48:16

在找到答案之后,我认为此页面可能会有所帮助。 https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation 不确定声明合并的历史,但是它说明了为什么以下内容可以工作。

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

window.MyNamespace = window.MyNamespace || {};
Gil2020/05/26 09:48:16

创建一个名为global.d.tseg 的文件,/src/@types/global.d.ts然后定义如下接口:

interface Window {
  myLib: any
}

参考:https : //www.typescriptlang.org/docs/handbook/declaration-files/templates/global-d-ts.html

达蒙2020/05/26 09:48:16

TypeScript不会对字符串属性执行类型检查。

window["newProperty"] = customObj;

理想情况下,应避免使用全局变量方案。我有时用它来调试浏览器控制台中的对象。

2020/05/26 09:48:16

如果您使用的是Typescript 3.x,则可以declare global在其他答案中省略该部分,而只需使用:

interface Window {
  someValue: string
  another: boolean
}

这在使用Typescript 3.3,WebPack和TSLint时与我合作。

Mandy村村2020/05/26 09:48:16

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

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

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

最后,从这里

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

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

示例如下:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

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

神离2020/05/26 09:48:16

要使其保持动态,只需使用:

(<any>window).MyNamespace
Tony凯2020/05/26 09:48:16

可接受的答案是我曾经使用的答案,但是使用TypeScript 0.9。*时,它将不再起作用。Window接口的新定义似乎完全取代了内置定义,而不是对其进行了扩充。

我改为这样做:

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

declare var window: MyWindow;

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

武藏2020/05/26 09:48:15

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

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

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

基本上,您需要扩展现有window接口以向其介绍新属性。

伽罗2020/05/26 09:48:15

使用TSX?没有其他答案对我有用。

这是我所做的:

(window as any).MyNamespace