扩展node.js中的TypeScript全局对象

m1m5dgzv  于 2023-01-08  发布在  Node.js
关注(0)|答案(9)|浏览(243)

我有一个node.js应用程序,它将一些配置信息附加到global对象:

global.myConfig = {
    a: 1,
    b: 2
}

TypeScript编译器不喜欢这样,因为Global类型没有名为myConfig的对象:
TS2339:类型“Global”上不存在属性“myConfig”。
我不想这么做:

global['myConfig'] = { ... }

我如何扩展Global类型以包含myConfig,或者只是让TypeScript闭嘴并相信我?
我不想修改node.d.ts中的声明,我看到SO post并尝试了以下操作:

declare module NodeJS  {
    interface Global {
        myConfig: any
    }
}

作为扩展现有Global接口的一种方式,但似乎没有任何效果。

kr98yfug

kr98yfug1#

node@16开始,NodeJS.Global接口has been removed支持globalThis
您可以在模块文件中将新的全局变量声明为:

declare global {
  var NEW_GLOBAL: string;
}

在非模块文件(没有顶级导入/导出)中为:

declare var NEW_GLOBAL: string;

重要提示:变量必须声明为varletconst变量不会显示在globalThis上。

hrirmatl

hrirmatl2#

我看到这个如此职位,并尝试这样:
您可能有类似vendor.d.ts的代码:

// some import 
// AND/OR some export

declare module NodeJS  {
    interface Global {
        spotConfig: any
    }
}

你的文件需要清除任何根级别importexports。这将把文件变成一个 * 模块 *,并断开它与 * 全局类型声明命名空间 * 的连接。
更多信息:https://basarat.gitbooks.io/typescript/content/docs/project/modules.html

vql8enpb

vql8enpb3#

为了避免Typescript声明类似于以下内容:
TS2339:类型"Global"上不存在属性"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);
dgsult0t

dgsult0t4#

将下面的文件放入项目的根目录中是有效的。
global.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"
    ]
}
oipij1gg

oipij1gg5#

使用“namespace”而不是“module "声明自定义TypeScript

如果你使用上面的任何一个答案,并且正在使用一个新版本的Typescript,你会得到一个关于使用**“module”的唠叨。你应该考虑命名空间。
为了满足这里的需求,实际上需要的不仅仅是扩展Global接口,如果希望从
“globalThis”**上下文直接访问该类型,还需要创建一个常量。

**注意:当OP询问对象文字时,过程与您在下面看到的相同。您只需根据需要定义接口,然后将“debug:“更改为myConfig或任何您想要的类型,而不是将“Debug”**类型作为函数。

// 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}`)
bprjcwpo

bprjcwpo6#

唯一对我有效的是:

// 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
kfgdxczn

kfgdxczn7#

对我有效的是:

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"]
}
dvtswwa3

dvtswwa38#

复制another post的答案:
这就是未来。

// Way 1
var abc: number
globalThis.abc = 200 // no error

// Way2
declare var age: number
globalThis.age = 18 // no error
l7mqbcuq

l7mqbcuq9#

我可以同时获得类型检查和代码智能。

declare namespace NodeJS {
  interface Global {
    property: string
  }
}

但是接口Global指向global.GLOBAL
你能得到正确的类型检查,是因为:

declare var global: NodeJS.Global & typeof globalThis;

但是使用global.property并不能获得更好的代码智能,除非使用global.GLOBAL.property
因此,您需要定义全局变量global和扩展接口Global

// myglobal.d.ts
declare namespace NodeJS {
  interface Global {
    property: string
  }
}
declare var global: NodeJS.Global & typeof globalThis

现在,您可以在键入global.时获得property智能

相关问题