我通过在 window
上显式设置属性来为我的对象设置全局命名空间。
window.MyNamespace = window.MyNamespace || {};
TypeScript 强调 MyNamespace
并抱怨:
“窗口”类型的值上不存在属性“MyNamespace”任何“
我可以通过将 MyNamespace
声明为环境变量并删除 window
显式性来使代码工作,但我不想这样做。
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
我怎样才能保留 window
并让 TypeScript 满意?
作为旁注,我发现 TypeScript 抱怨特别有趣,因为它告诉我 window
是 any
类型,它肯定可以包含任何东西。
我刚刚在 another Stack Overflow question's answer 中找到了答案。
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
基本上,您需要扩展现有的 window
接口来告诉它您的新属性。
要保持动态,只需使用:
(<any>window).MyNamespace
请注意,这可能不适用于 TSX,因为编译器可能认为 <any>
是 TSX 元素。查看 this answer 以了解与 TSX 兼容的类型断言。
as
而不是 <>
。请参阅 @david-boyd 的 answer below。
this
- return (<any> this)['something in scope']
也是如此
/* tslint:disable */
在该行禁用 tslint
使用 Svelte 还是 TSX?其他答案都不适合我。
这是我所做的:
(window as any).MyNamespace
(<any> window).MyNamespace
相同
<any>
被解释为 JSX,而不是类型转换。
从 TypeScript ^3.4.3 开始,此解决方案不再有效
或者...
你可以输入:
window['MyNamespace']
而且您不会收到编译错误,它的工作原理与键入 window.MyNamespace
相同。
^3.4.3
中不起作用。 TypeScript error: Element implicitly has an 'any' type because type 'Window' has no index signature. TS7017
全局变量是“邪恶的” :) 我认为获得可移植性的最佳方法是:
首先你导出界面:(例如,./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 和最新版本进行测试!
对于那些使用 Angular CLI 的人来说,这很简单:
文件 src/polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
文件 my-custom-utils.ts
window.myCustomFn = function () {
...
};
如果您使用 IntelliJ IDEA,您还需要在 IDE 中更改以下设置,然后才能使用新的 polyfills:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
declare global
是诀窍,这个答案并不是真正特定于 Angular CLI ......
接受的答案是我以前使用的答案,但是使用 TypeScript 0.9.* 它不再有效。 Window
接口的新定义似乎完全取代了内置定义,而不是对其进行扩充。
我已经开始这样做了:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
更新:使用 TypeScript 0.9.5,接受的答案再次起作用。
export default class MyClass{ foo(){ ... } ... }
interface MyWindow extends Window{ mc: MyClass }
declare var window: MyWindow
window.mc = new MyClass()
然后您可以调用 foo() 例如从 Chrome 开发工具控制台,如 mc.foo()
declare var...
。
Window
,因为它不是一个普通的窗口。仅仅规避类型检查或试图欺骗 TS 也不是解决问题的方法。
如果您需要使用需要使用 import
的自定义类型来扩展 window
对象,可以使用以下方法:
窗口.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
请参阅手册“声明合并”部分中的Global Augmentation。
创建一个名为 global.d.ts
的文件,例如 /src/@types/global.d.ts
,然后定义如下接口:
interface Window {
myLib: any
}
参考:Global .d.ts
大多数其他答案并不完美。
其中一些只是抑制了 show 的类型推断。
其他一些只关心全局变量作为命名空间,而不是接口/类
今天早上我也遇到了类似的问题。我在 Stack Overflow 上尝试了很多“解决方案”,但没有一个绝对不会产生类型错误并在 IDE(WebStorm 或 Visual Studio Code)中启用触发类型跳转。
最后,来自 Allow module definitions to be declared as global variables #3180
我找到了一个合理的解决方案来为作为接口/类和命名空间的全局变量附加类型。
示例如下:
// typings.d.ts
declare interface Window {
myNamespace?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
上面的代码将命名空间 MyNamespace
和接口 MyNamespace
的类型合并到全局变量 myNamespace
中(window 的属性)。
我不需要经常这样做。我遇到的唯一情况是在将 Redux DevTools 与中间件一起使用时。
我只是做了:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
或者你可以这样做:
let myWindow = window as any;
然后myWindow.myProp = 'my value';
在找到答案后,我认为此页面可能会有所帮助:
我不确定声明合并的历史,但它解释了为什么以下可以工作。
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
从 3.4 版开始,TypeScript 已支持 globalThis
。请参阅 Type-checking for 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 中。
lib.d.ts
将 window
声明为类型 Windows & globalThis
,这意味着这两种类型合并在一起。
使用 create-react-app v3.3,我发现实现此目的的最简单方法是在自动生成的 react-app-env.d.ts
中扩展 Window
类型:
interface Window {
MyNamespace: any;
}
TypeScript 不对字符串属性执行类型检查。
window["newProperty"] = customObj;
理想情况下,应该避免全局变量场景。我有时用它来调试浏览器控制台中的对象。
如果您使用的是 TypeScript 3.x,则可以省略其他答案中的 declare global
部分,而只需使用:
interface Window {
someValue: string
another: boolean
}
这在使用 TypeScript 3.3、Webpack 和 TSLint 时对我有用。
^3.4.3
中不起作用。这个答案对我有用stackoverflow.com/a/42841166/1114926
如果您使用的是 TypeScript Definition Manager,请按照以下步骤操作!
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 || {};
typings
已在 Typescript 2.0(2016 年中)中过时,并已由所有者存档。
使用
window["MyNamespace"] = window["MyNamespace"] || {};
应该没问题,因为它使用的是字符串属性,但是如果你真的想要一个单独的窗口并组织你的代码,你可以扩展窗口对象:
interface MyNamespacedWindow extends Window {
MyNamespace: object;
}
declare var window: MyNamespacedWindow;
declare
上抛出一个 TS 错误,说 Modifiers cannot appear here. ts(1184)
。有任何想法吗?
首先,您需要在当前范围内声明窗口对象。因为 TypeScript 想知道对象的类型。由于窗口对象是在其他地方定义的,因此您不能重新定义它。
但是你可以声明如下:
declare var window: any;
这不会重新定义窗口对象,也不会创建另一个名为 window
的变量。这意味着 window 是在其他地方定义的,您只是在当前范围内引用它。
然后您可以简单地通过以下方式引用您的 MyNamespace 对象:
window.MyNamespace
或者,您可以简单地通过以下方式在 window
对象上设置新属性:
window.MyNamespace = MyObject
现在 TypeScript 不会抱怨了。
供参考(这是正确答案):
在 .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");
创建一个扩展 Window 的自定义接口,并将您的自定义属性添加为可选。
然后,让 customWindow 使用自定义界面,但重视与原始窗口。
它适用于 TypeScript 3.1.3。
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
// In typings.d.ts(is Global)
export declare global {
interface Window {
__PUBLIC__: string;
}
}
https://i.stack.imgur.com/9DPDK.png
Cypress
和 app
。通过从各自的库中导入这两种类型并相应地声明属性,我能够很好地实现这一点:``` import { Cypress } from 'cypress';从'vue'导入{ ComponentPublicInstance }; // 将 Cypress 和应用程序添加到全局窗口以进行测试 export declare global { interface Window { Cypress: Cypress;应用程序:组件公共实例; } } ```
对于那些想要在 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
为了解决这个问题,您可以使用将 window
转换为 <any>
的建议,这样您就可以做到
(window as any)[DynamicObject.key]
完整和简短的答案
1-将 typeRoots 属性添加到 tsconfig.json:
{
"compilerOptions": {
...
"typeRoots": ["src/@types", "node_modules/@types"]
...
}
}
2- 扩展窗口类型
// file: src/@types/global.d.ts
declare global {
interface Window { customProperty: <type>; }
}
(window as { test: string } & Window & typeof globalThis).test = `Hello World`;
我今天想在 Angular (6) 库中使用它,我花了一段时间才让它按预期工作。
为了让我的库使用声明,我必须对声明全局对象的新属性的文件使用 d.ts
扩展名。
所以最后,该文件最终得到如下内容:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
创建后,不要忘记在您的 public_api.ts
中公开它。
那是为我做的。
TypeScript 会阻止在未分配具有所需属性或已分配给 any
的类型的情况下访问对象,因此您可以使用可选链接:
window?.MyNamespace = 'value'
我使用没有声明。我的示例如下所示:
https://i.stack.imgur.com/qG8yc.png
[2022]:我们必须在 React 或 Nextjs 项目中扩展“窗口”对象。我们可以使用以下步骤来解决这个问题。
在 src 文件夹名称中创建一个文件夹作为类型。
在类型文件夹名称中创建一个文件为 index.d.ts
将此代码写入 index.d.ts 文件中。出口 {};声明全局 { interface Window { NameSpace: any; } } 窗口.名称空间=窗口.名称空间|| {};
https://i.stack.imgur.com/Shpiv.png
现在最后一个变化。
更改“tsConfig.json”文件。继承节点模块类型和我们的类型。
{
"compilerOptions": {
...
"typeRoots": [
"./node_modules/@types",
"./src/types"
],
....
}
https://i.stack.imgur.com/Pyf4N.png
不定期副业成功案例分享
.d.ts
文件中声明时才有效。在使用导入和导出本身的.ts
文件中使用时,它不起作用。请参阅this answer。declare global { interface Window { ... } }
与 TypeScript 2.5.2 一起使用,不需要上面提到的.d.ts
文件declare interface Window { __GLOBAL_VAR__: any }
export {}
。