我有一个node.js应用程序,它将一些配置信息附加到global
对象:
global.myConfig = {
a: 1,
b: 2
}
TypeScript 编译器不喜欢这样,因为Global
类型没有名为 myConfig
的对象:
TS2339:类型"全局"上不存在属性"myConfig"。
我不想这样做:
global['myConfig'] = { ... }
如何扩展Global
类型以包含myConfig
或只是告诉 TypeScript 闭嘴并信任我?我更喜欢第一个。
我不想更改node.d.ts
中的声明。我看到了这个SO帖子并尝试了这个:
declare module NodeJS {
interface Global {
myConfig: any
}
}
作为扩展现有Global
接口的一种方式,但它似乎没有任何效果。
截至node@16
,NodeJS.Global
接口已被删除,取而代之的是globalThis
。
您可以在模块文件中将新的全局变量声明为:
declare global {
var NEW_GLOBAL: string;
}
在非模块文件(无顶级导入/导出)中,如下所示:
declare var NEW_GLOBAL: string;
重要说明:变量必须声明为 var
。 let
和const
变量不会显示在globalThis
上。
我看到了这个SO帖子并尝试了这个:
你可能有类似vendor.d.ts
:
// some import
// AND/OR some export
declare module NodeJS {
interface Global {
spotConfig: any
}
}
您的文件需要清除任何根级别import
或exports
。这会将文件转换为模块,并将其与全局类型声明命名空间断开连接。
更多 : https://basarat.gitbooks.io/typescript/content/docs/project/modules.html
为了避免 Typescript 声明如下内容:
TS2339:类型"全局"上不存在属性"myConfig"。
我建议定义自定义类型。我在项目中src/types/custom.d.ts
文件下执行此操作:
declare global {
namespace NodeJS {
interface Global {
myConfig: {
a: number;
b: number;
}
}
}
}
然后我确保这些被tsconfig.json
文件中的 Typescript 考虑:
{
...
"files": [
...
"src/types/custom.d.ts"
]
}
现在,您可以安全地使用自定义属性:
console.log(global.myConfig.a);
将以下文件放入我们项目的根目录中是有效的。
全球.d.ts
declare namespace NodeJS {
export interface Global {
myConfig: any
}
}
我们正在使用 "@types/node": "^7.0.18"
和 TypeScript Version 2.3.4
。我们的 tsconfig.json 文件看起来像这样:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
},
"exclude": [
"node_modules"
]
}
使用"命名空间"而不是"模块"来声明自定义 TypeScript
如果您使用上述任何答案并且使用的是较新版本的 Typescript,您会对使用"模块"感到烦恼。您应该改为考虑命名空间。
为了满足此处的要求,您实际上需要的不仅仅是扩展全局接口。如果您希望直接从"globalThis"上下文访问该类型,则还需要创建一个具有该类型的常量。
注意:当OP询问对象文字时,该过程与您在下面看到的相同。而不是"调试"类型是一个函数,您只需根据需要定义接口,然后将"debug:"更改为myConfig或任何您想要的内容。
// typically I'll store the below in something like "typings.d.ts"
// this is because, at least typically, these overrides tend to
// be minimal in nature. You could break them up and Typescript
// will pick them up if you wish.
// Augmentations for the global scope can only be directly nested
// in external modules or ambient module declarations.
export {}
declare global {
// Definition or type for the function.
type Debug = (label: string) => (message: any, ...args: any[]) => void
// If defining an object you might do something like this
// interface IConfig { a: number, b: number }
// Extend the Global interface for the NodeJS namespace.
namespace NodeJS {
interface Global {
// Reference our above type,
// this allows global.debug to be used anywhere in our code.
debug: Debug
}
}
// This allows us to simply call debug('some_label')('some debug message')
// from anywhere in our code.
const debug: Debug
}
如何使用上述内容
为了完整起见,在这个例子中,我们所做的只是定义一个全局,以便我们可以记录一个简单的调试消息。以下是我们如何将该方法绑定到全局上下文。
global.debug = (label: string) => (message: any, ...args: any[]) => console.log(message, ...args)
我们也可以直接调用我们的全局调试方法:
debug('express')(`${req.method}: ${req.url}`)
唯一对我有用的是:
// lib/my.d.ts
import Global = NodeJS.Global;
export interface CDTGlobal extends Global {
cdtProjectRoot: string
}
然后在其他文件中使用它,例如
import {CDTGlobal} from "../lib/my.d.ts";
declare const global: CDTGlobal;
const cwd = global.cdtProjectRoot; // works
对我有用的是:
declare global {
module NodeJS {
interface Global {
myConfig: any;
}
}
}
global.myConfig = 'it works!';
唯一的缺点是使用它时,您必须关闭 ESLint 规则 @typescript-eslint/no-namespace
.
为了完整起见,这是我tsconfig.json
:
{
"compilerOptions": {
"declaration": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": ["dom", "es2017"],
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "dist",
"removeComments": true,
"resolveJsonModule": true,
"rootDir": "src",
"sourceMap": true,
"strict": true,
"target": "es6"
},
"exclude": ["dist", "node_modules"]
}
复制我对另一篇文章的回答:
全球这就是未来。
// Way 1
var abc: number
globalThis.abc = 200 // no error
// Way2
declare var age: number
globalThis.age = 18 // no error
我可以同时获得类型检查和代码智能。
declare namespace NodeJS {
interface Global {
property: string
}
}
但是接口Global
指向global.GLOBAL
。
你能得到正确的类型检查,是因为:
declare var global: NodeJS.Global & typeof globalThis;
但是使用global.property
无法获得更好的代码智能,除非使用global.GLOBAL.property
。
因此,您需要定义全局 var global
并扩展接口Global
两者:
// myglobal.d.ts
declare namespace NodeJS {
interface Global {
property: string
}
}
declare var global: NodeJS.Global & typeof globalThis
现在,当您键入global.
时,您可以获得property
智能
我相信这应该有效
declare global {
var user: string;
function greeting(user: string, message: string): string;
}
export {};
确保您使用的是 var
关键字,并且您正在d.ts
文件中进行设置。 例如global.d.ts
.
不要忘记添加导出语句
您现在可以在代码库中的任何位置访问它,例如global.person