在node.js中扩展TypeScript全局对象
在node.js中扩展TypeScript全局对象
我有一个node.js应用程序,将一些配置信息附加到global
对象上:
global.myConfig = { a: 1, b: 2 }
TypeScript编译器不喜欢这样做,因为Global
类型中没有名为myConfig
的对象:
TS2339: 在类型“Global”上不存在属性“myConfig”。
我不想这样做:
global['myConfig'] = { ... }
我要么如何扩展Global
类型以包含myConfig
,要么告诉TypeScript闭嘴相信我?我更倾向于第一种方式。
我不想更改node.d.ts
中的声明。我看到了这个SO帖子并尝试了这个:
declare module NodeJS { interface Global { myConfig: any } }
作为扩展现有Global
接口的一种方式,但似乎没有任何效果。
问题的出现原因是在使用TypeScript编写Node.js应用程序时,需要扩展全局对象,即在全局范围内添加自定义属性或方法。然而,在某些情况下,通过在vendor.d.ts
文件中声明NodeJS.Global
接口来扩展全局对象可能会导致问题。
解决方法是确保vendor.d.ts
文件中没有任何根级别的import
或export
语句。这样可以避免将文件转换为模块,从而断开它与全局类型声明命名空间的连接。
此外,还有一个解决方案是使用declare global
语法来声明全局命名空间的扩展。通过在vendor.d.ts
文件中添加类似于declare global { namespace NodeJS { ... }}
的语句,可以同时实现全局命名空间的扩展和模块的导出。
对于在外部模块中使用接口作为类型的情况,可以使用import
语句将外部模块导入,并将其接口用作类型。例如,可以使用import { Sequelize } from 'sequelize';
来导入外部模块,并将Sequelize.Sequelize
用作spotConfig
的类型。
总结起来,解决问题的方法主要有两种:确保vendor.d.ts
文件不包含根级别的import
或export
语句,并使用declare global
语法声明全局命名空间的扩展。另外,可以使用import
语句将外部模块导入,并将其接口用作类型。
问题的出现是因为在TypeScript中,全局对象Global没有定义myConfig属性,因此会报错。解决方法是定义自定义类型并在项目的src/types/custom.d.ts文件中实现。在这个文件中,我们使用declare global关键字来扩展NodeJS的Global接口,添加myConfig属性的定义。接着,在tsconfig.json文件中确保TypeScript能够识别这个自定义类型,将src/types/custom.d.ts文件添加到files数组中。这样,我们就可以安全地使用自定义属性global.myConfig了。这个解决方法类似于在客户端使用declare global来扩展Window对象。最后,提问者询问是否有关于declare global语法的文档,但是他们在使用declare global时遇到了一个错误。
在Node.js中,NodeJS.Global
接口已经被移除,取而代之的是globalThis
。如果你想在模块文件中声明一个新的全局变量,可以使用以下代码:
declare global {
var NEW_GLOBAL: string;
}
如果是在非模块文件(没有顶级import/export)中声明,可以使用以下代码:
declare var NEW_GLOBAL: string;
需要注意的是,变量必须声明为var
,let
和const
变量不会出现在globalThis
中。
截至2021年9月,这是唯一有效的解决方法(Node v14 LTS)。很好地指出了在TS声明中使用var的重要性,帮助了我很多,非常感谢!
对我来说没有起作用,编译器仍然报错,显示以下消息:'Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature'。
在Server.ts中声明和设置的NEW_GLOBAL在例如UserController中如何使用?我需要导入它吗?Typescript如何知道它已经在Server.ts中声明过了?
我不确定如何在Node18中做到这一点,最后我使用了-ignore,这些东西过于复杂了。
在模块文件中使用declare global { ... }
,并且在tsconfig.json
中设置"isolatedModules": true
,我需要在声明文件中添加一个空的导出对象export {}
才能使其起作用。
非常感谢你指出变量必须声明为var的重要性。我建议你通过增大字体尺寸并将其放在顶部来更加突出这一点。
你可以使用global.NEW_GLOBAL
或globalThis.NEW_GLOBAL
来引用它。