Node.js全局变量和TypeScript

14

我需要一些具有强类型的全局变量。

如此提及: 在node.js中扩展TypeScript全局对象,为了向global变量添加字段,我需要添加一个.d.ts文件,该文件扩展了在node.d.ts中指定的Global接口。

同时,正如Basarat所提到的:

您的文件必须清除任何根级别的导入或导出。这将把文件转换为模块,并将其与全局类型声明命名空间断开连接。

现在,我需要在Global接口上拥有一些字段,这些字段的类型是我创建的自定义接口:

declare namespace NodeJS{
    interface Global {
        foo: Foo
        bar: Bar
    }
}

我非常不愿意使用any类型。

我可以将所有接口声明移动/复制到此声明文件中,但对我来说这是一个糟糕的解决方案,因为Foo和Bar反过来聚合了许多其他接口的字段,包括Moment等第三方接口。

我需要解决这个悖论的方法。


你找到解决方案了吗? - Sid Verma
3个回答

13

这是一种方法。我不知道这是否是做事情的“正确”方式,但它对我在TypeScript 3.7.4中有效。

  1. 假设您的源文件位于文件夹src中,请创建一个名为src/types的新文件夹,并在此文件夹中创建一个名为global.d.ts的文件。
  2. 使用以下策略之一编写您的声明:
    • 如果您需要将外部类型导入到声明文件中,请使用以下语法:
import { Express } from 'express';

declare global {
  namespace NodeJS {
    interface Global {
      __EXPRESS_APP__: Express;
    }
  }
}
  • 如果你的声明文件没有包含任何导入(import)内容,上述方法将不起作用,你需要使用以下语法:

如果你的声明文件没有包含任何导入(import)内容,上述方法将无效,你需要改用以下语法。
declare namespace NodeJS {
  interface Global {
    __CONNECTION_COUNT__: number;
  }
}
  1. 请确保您的global.d.ts文件(以及您可能添加到src/types的任何其他文件)被TypeScript编译器捕获,方法是将以下内容添加到您的tsconfig.json文件中:
{
  "paths": {
    "*": ["node_modules/*", "src/types/*"]
  }
}
  1. 在你的代码中正常使用全局变量。
// Below, `app` will have the correct typings
const app = global.__EXPRESS_APP__;

7

我发现这个方法可行。

创建一个文件,在NodeJS.Global接口上声明任意类型的属性。这个文件不能包含导入或引用。

node.d.ts

declare namespace NodeJS{
    interface Global {
        foo: any
    }
}

在第二个文件中,您声明一个具有正确类型的全局变量。

global.d.ts

import IFoo from '../foo'

declare global {

  const foo:Ifoo

}

1
请注意,当使用此方法时,所有 global.foo 的用法仍将是 any 类型,这很恼人。 但是,您至少可以全局将 foo 用作 Ifoo 类型。 虽然还不错,但有待改进。 我希望 TypeScript 团队能够发表有关最佳实践的评论;这已经是 TypeScript 存在的问题了。 - Jamie Birch
我遇到了这个错误 TSError: ⨯ 无法编译TypeScript: src/index.ts:3:8 - error TS2339: Property 'env' does not exist on type 'Global' while compiling - just coding
这确实起作用了。这是我找到的唯一可行的解决方案。在我的情况下,我只有基本属性,因此在这种情况下,您只需要 node.d.ts 全局{ foo: string, bar: string } ... - Kat Lim Ruiz

1

这对我有用(node v16.13.2)

  1. 在你的根目录下创建文件 types/global.d.ts
declare global {
    var __root: string
}
export {}

请注意,__root 使用 var 关键字声明。它也可以与 letconst 一起使用,但在这种情况下,__root 将具有 any 类型。我不知道为什么;) 如果有人能解释一下,那就太好了。
  1. 配置你的 tsconfig.json
{
    "compilerOptions": {
        "typeRoots": [
            "types"
        ],
    }
}
  1. 在你的代码中使用已声明的变量
// app.ts (entry point)
import path from 'path'
global.__root = path.join(__dirname)

// anyFileInProject.ts
console.log(__root)  // will display root directory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接