【问题标题】:Node.js global variable and TypeScriptNode.js 全局变量和 TypeScript
【发布时间】:2017-06-02 16:32:18
【问题描述】:

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

正如这里提到的:Extending TypeScript Global object in node.js,为了向global 变量添加字段,我需要添加一个扩展在node.d.ts 中指定的Global 接口的.d.ts 文件。

另外,正如巴萨拉特所说:

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

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

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

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

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

我需要解决这个悖论

【问题讨论】:

  • 您找到解决方案了吗?

标签: javascript node.js oop typescript module


【解决方案1】:

这对我有用(节点 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

【讨论】:

    【解决方案2】:

    这是一种方法。我不知道这是否是“正确”的做事方式,但它适用于 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;
        }
      }
    }
    
    • 如果您的声明文件不包含任何导入,上述方法将不起作用,您需要改用以下语法:
    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__;
    

    【讨论】:

      【解决方案3】:

      我发现这行得通。

      有一个文件在 NodeJS.Global 接口上声明任何类型的属性。此文件必须没有导入或引用。

      node.d.ts

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

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

      global.d.ts

      import IFoo from '../foo'
      
      declare global {
      
        const foo:Ifoo
      
      }
      

      【讨论】:

      • 请注意,当使用此方法时,所有global.foo 用法仍然会令人讨厌地属于any 类型。但是,您至少可以将foo 用作全局Ifoo 类型。但是,足以继续前进。我希望 TypeScript 团队对此的最佳实践发表评论;只要 TypeScript 存在,这就是一个问题。
      • 我收到此错误 TSError: ⨯ 无法编译 TypeScript: src/index.ts:3:8 - 错误 TS2339: 编译时类型 'Global' 上不存在属性 'env'跨度>
      • 这确实有效。我发现唯一可行的解​​决方案。就我而言,我只有原始属性,所以在这种情况下,您只需要 node.d.ts global{ foo: string, bar: string } ...
      猜你喜欢
      • 1970-01-01
      • 2011-07-23
      • 2020-02-10
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多