乐闻世界logo
搜索文章和话题

Typescript 如何在显式的设置 window 的新属性?

7 个月前提问
3 个月前修改
浏览次数245

8个答案

1
2
3
4
5
6
7
8

在TypeScript中,如果我们想要向window对象添加一个新的属性,我们需要扩展Window接口,并告知TypeScript我们正在添加的类型。由于window是全局对象,TypeScript需要知道属性的类型以确保类型安全。这可以通过声明合并来完成。

这里是一个例子,展示如何向window对象添加名为myNewProperty的新属性:

typescript
// 首先,声明合并来扩展现有的Window接口 interface Window { myNewProperty: string; } // 然后,可以安全地向window添加新属性 window.myNewProperty = "Hello, World!"; // 使用该属性时,TypeScript会知道其类型 console.log(window.myNewProperty); // 输出:"Hello, World!"

在这个例子中,我们首先通过声明一个同名的Window接口来扩展全局的Window接口。这里的关键是使用interface这个关键字,而不是用type。声明合并允许我们安全地添加myNewProperty属性,而不会破坏window对象上的其他属性或方法的类型定义。

现在,TypeScript知道window对象上存在一个名为myNewProperty的属性,并且它的类型是string。这样,当我们给window.myNewProperty赋值时,TypeScript将允许任何字符串类型的值,并在我们尝试赋予不兼容的类型时提供错误警告。

还需要注意的是,在实际的前端项目中直接修改window对象并不是一个好的做法,因为这可能会造成全局状态污染,很难追踪和维护。通常,我们应该尽量避免向全局作用域添加额外的状态或功能,除非真的有必要这样做。

2024年6月29日 12:07 回复

I just found the answer to this in another Stack Overflow question's answer.

shell
declare global { interface Window { MyNamespace: any; } } window.MyNamespace = window.MyNamespace || {};

Basically, you need to extend the existing window interface to tell it about your new property.

2024年6月29日 12:07 回复

To keep it dynamic, just use:

shell
(<any>window).MyNamespace

Note that this may not work with TSX because the compiler might think that the <any> is a TSX element. Check out this answer for type assertion that is compatible with TSX.

2024年6月29日 12:07 回复

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

Here's what I did:

shell
(window as any).MyNamespace
2024年6月29日 12:07 回复

As of TypeScript ^3.4.3, this solution no longer works

Or...

you can just type:

shell
window['MyNamespace']

And you won’t get a compile error and it works the same as typing window.MyNamespace.

2024年6月29日 12:07 回复

Globals are "evil" :) I think the best way to also have the portability is:

First you export the interface: (for example, ./custom.window.ts)

shell
export interface CustomWindow extends Window { customAttribute: any; }

Second, you import

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

Third, cast the global variable window with CustomWindow:

shell
declare let window: CustomWindow;

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

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

Tested with TypeScript 2.4.x and newest!

2024年6月29日 12:07 回复

在 TypeScript 中,你通常不应该直接向 window 对象添加新的属性,因为这样做会破坏全局作用域的安全性和可预测性。但是,如果你确实需要这样做(例如,为了与第三方库集成),你可以通过扩展 Window 接口来显式声明新属性。

下面是一个例子,展示了如何在 TypeScript 中给 window 对象添加一个名为 myCustomProperty 的新属性:

typescript
// 首先,使用 TypeScript 的声明合并特性扩展全局 Window 接口 declare global { interface Window { myCustomProperty: string; } } // 现在你可以安全地设置 window 的新属性 window.myCustomProperty = 'some value'; // 也可以读取该属性 console.log(window.myCustomProperty);

在这个例子中,我们首先使用 declare global 语句来扩展全局作用域中的 Window 接口。然后,我们声明了 myCustomPropertystring 类型的属性。这样 TypeScript 编译器就知道 window 对象上存在这个新属性,并且知道它的类型。这允许你在代码的其他部分安全地使用 window.myCustomProperty 而不会得到类型错误。

请注意,如果你正在一个模块环境中工作(即任何包含顶级 import 或 export 声明的文件),你需要将 declare global 包装在一个模块声明中,否则它不会被视为全局声明。例如:

typescript
export {}; // 这个文件现在是一个模块 declare global { interface Window { myCustomProperty: string; } } window.myCustomProperty = 'some value';

在这里,export {} 把文件转变成了一个模块,允许我们使用 declare global 来做全局的声明。如果你不包括 export {},那么 declare global 会引发一个错误,因为 TypeScript 会认为你正在试图在模块作用域中声明一个全局变量。

2024年6月29日 12:07 回复

在TypeScript中,向window对象添加新属性需要两个步骤:

  1. 扩展Window接口:由于TypeScript使用结构类型系统,我们可以通过声明合并来扩展现有的类型定义。对于window对象,我们需要扩展全局Window接口。

  2. 设置属性:在扩展了接口之后,我们就可以像在JavaScript中一样向window对象添加属性。

下面是一个如何向window对象添加新属性的例子:

typescript
// Step 1: Extend the Window interface with the new property interface Window { myCustomProperty: string; } // Step 2: Add the property to the window object window.myCustomProperty = "This is a custom property on the window object"; console.log(window.myCustomProperty); // 输出: This is a custom property on the window object

在上面的例子中,我们首先扩展了Window接口来包含一个名为myCustomProperty的字符串属性。然后,我们实际上为window对象设置了这个属性。

重要的是要注意,这样的操作不是最佳实践,因为直接向全局对象添加属性会导致全局命名空间的污染。在实际的TypeScript项目中,我们通常会避免这么做,除非在某些特殊情况下确实需要,比如在进行polyfill或者与第三方库集成时。

此外,如果你的TypeScript编译选项中设置了strict模式或者noImplicitAnytrue,你可能还需要确保对window对象的扩展是在正确的作用域中完成的,例如在一个全局的.d.ts文件中,这样才不会影响其他文件中的类型检查。

2024年6月29日 12:07 回复

你的答案