975

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

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

TypeScript 强调MyNamespace并抱怨:

“窗口”类型的值上不存在属性“MyNamespace”任何“

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

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

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

作为旁注,我发现 TypeScript 抱怨特别有趣,因为它告诉我那windowany绝对可以包含任何东西的类型。

4

28 回答 28

1128

我刚刚在另一个 Stack Overflow question's answer中找到了答案。

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

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

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

于 2012-10-03T13:46:44.400 回答
515

要保持动态,只需使用:

(<any>window).MyNamespace

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

于 2015-06-09T19:18:26.133 回答
267

使用 Svelte 还是 TSX?其他答案都不适合我。

这是我所做的:

(window as any).MyNamespace
于 2016-08-15T23:25:22.107 回答
223

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

或者...

你可以输入:

window['MyNamespace']

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

于 2012-11-20T19:36:21.393 回答
110

全局变量是“邪恶的” :) 我认为获得可移植性的最佳方法是:

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

export interface CustomWindow extends Window {
    customAttribute: any;
}

二、你进口

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

三、用CustomWindow强制转换全局变量window:

declare let window: CustomWindow;

这样,如果您将它与窗口对象的现有属性一起使用,则在不同的 IDE 中也没有红线,所以最后尝试:

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

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

于 2017-07-27T13:28:39.760 回答
81

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

我已经开始这样做了:

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

declare var window: MyWindow;

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

于 2013-08-27T21:22:53.927 回答
79

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

文件src/polyfills.ts

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

文件my-custom-utils.ts

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

如果您使用的是IntelliJ IDEA,您还需要在 IDE 中更改以下设置,然后才能使用新的polyfill

> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
于 2017-03-21T13:38:46.957 回答
59

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

窗口.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

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

于 2016-10-23T15:24:04.003 回答
44

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

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

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

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

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

示例如下:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

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

于 2017-05-19T03:26:24.543 回答
40

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

interface Window {
  myLib: any
}

参考:全球 .d.ts

于 2020-01-09T19:50:47.813 回答
35

我不需要经常这样做。我遇到的唯一情况是使用Redux DevTools和中间件。

我只是做了:

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

或者你可以这样做:

let myWindow = window as any;

进而myWindow.myProp = 'my value';

于 2018-06-06T13:13:12.333 回答
19

在找到答案后,我认为此页面可能会有所帮助:

全局增强

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

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

window.MyNamespace = window.MyNamespace || {};
于 2017-03-16T17:38:24.857 回答
16

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

window["newProperty"] = customObj;

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

于 2019-06-18T19:01:08.130 回答
16

从 3.4 版开始,TypeScript 已支持globalThis. 请参阅globalThis 的类型检查

从上面的链接

// in a global file:
var abc = 100;
// Refers to 'abc' from above.
globalThis.abc = 200;
window.abc = 300; // window object can also be used.

操场

“全局”文件是没有任何导入/导出语句的文件。所以声明var abc;可以写成.d.ts

于 2021-02-24T11:59:40.153 回答
15

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

interface Window {
    MyNamespace: any;
}
于 2020-03-04T02:51:37.437 回答
14

如果您使用的是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 || {};
于 2016-11-19T21:31:52.870 回答
14

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

interface Window {
  someValue: string
  another: boolean
}

在使用 TypeScript 3.3、WebpackTSLint时,这对我有用。

于 2019-02-12T21:50:41.787 回答
13

使用

window["MyNamespace"] = window["MyNamespace"] || {};

应该没问题,因为它使用的是字符串属性,但是如果你真的想要一个单独的窗口并组织你的代码,你可以扩展窗口对象:

interface MyNamespacedWindow extends Window {
    MyNamespace: object;
}

declare var window: MyNamespacedWindow;
于 2020-07-13T04:07:43.447 回答
10

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

但是你可以声明如下:

declare var window: any;

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

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

window.MyNamespace

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

window.MyNamespace = MyObject

现在 TypeScript 不会抱怨了。

于 2019-05-31T22:41:02.710 回答
9

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

.d.ts定义文件中

type MyGlobalFunctionType = (name: string) => void

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

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Node.js 的想法相同:

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

现在您声明根变量(实际上将存在于窗口或全局上):

declare const myGlobalFunction: MyGlobalFunctionType;

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

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

最后在代码库的其他地方使用它,其中之一是:

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

myGlobalFunction("Kevin");
于 2017-04-20T15:50:22.427 回答
7

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

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

它适用于 TypeScript 3.1.3。

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {}
于 2018-11-12T07:29:48.543 回答
6

对于那些想要在window对象上设置计算或动态属性的人,您会发现使用该方法是不可能的declare global。澄清这个用例

window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature

你可能会尝试做这样的事情

declare global {
  interface Window {
    [DyanmicObject.key]: string; // error RIP
  }
}

以上会出错。这是因为在 TypeScript 中,接口不能很好地处理计算属性,并且会抛出类似的错误

A computed property name in an interface must directly refer to a built-in symbol

为了解决这个问题,你可以接受casting windowto的建议,<any>这样你就可以做到

(window as any)[DynamicObject.key]
于 2019-02-13T00:15:34.730 回答
2

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

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

所以最后,该文件最终得到如下内容:

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

一旦创建,不要忘记在你的public_api.ts.

那是为我做的。

于 2018-08-01T11:29:02.267 回答
2

完整和简短的答案

1-将typeRoots属性添加到tsconfig.json

{
  "compilerOptions": {
    ...
    "typeRoots": ["src/@types", "node_modules/@types"]
    ...
  }
}

2- 扩展Window

// file: src/@types/global.d.ts

declare global {
    interface Window { customProperty: <type>; }
}
于 2022-01-11T16:32:33.607 回答
2
(window as { test: string } & Window & typeof globalThis).test = `Hello World`;
于 2022-01-16T07:47:20.917 回答
2
// In typings.d.ts(is Global)
export declare global {
    interface Window {
        __PUBLIC__: string;
    }
}

在此处输入图像描述

于 2022-01-27T03:44:28.973 回答
0

TypeScript 会阻止在未分配具有所需属性或已分配给 的类型的情况下访问对象any,因此您可以使用可选链接:

window?.MyNamespace =  'value'
于 2020-11-06T07:20:41.460 回答
0

我使用没有声明。我的示例如下所示:

在此处输入图像描述

于 2022-02-09T10:21:03.883 回答