在TypeScript中使用process.env

Chr*_*ais 22 node.js typescript

如何在TypeScript中读取节点环境变量?

如果我使用process.env.NODE_ENV我有这个错误:

Property 'NODE_ENV' does not exist on type 'ProcessEnv'
Run Code Online (Sandbox Code Playgroud)

我安装@types/node但没有帮助.

Kar*_*ski 21

@types/node在项目中安装完之后,您可以准确地告诉TypeScript您的变量中存在哪些变量process.env

environment.d.ts

declare global {
  namespace NodeJS {
    interface ProcessEnv {
      GITHUB_AUTH_TOKEN: string;
      NODE_ENV: 'development' | 'production';
      PORT?: string;
      PWD: string;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

此方法将为您提供IntelliSense,并且还利用了字符串文字类型。

注意:以上代码段是模块扩充。包含模块扩展的文件必须是模块(而不是脚本)。模块和脚本之间的区别在于,模块至少具有一个import / export语句。

为了使TypeScript将文件视为模块,只需向其中添加一个import语句。可以是任何东西。甚至import * as ts from 'typescript'会做。

  • 事实证明,这是没有必要的。我只需要删除“声明全局”。 (6认同)
  • 请务必将“module.d.ts”添加到 tsconfig.json 文件中的 include 参数中。 (6认同)
  • 我在这里收到 TS 错误,“全局范围的增强只能直接嵌套在外部模块或环境模块声明中。” 这是我在 CRA 应用程序中的“react-app-env.d.ts”文件。对我来说,删除 `declare global` 并在 root 上执行 `declare namespace NodeJS` 工作。谢谢! (3认同)
  • 那是因为扩充只能在模块中进行,而不能在脚本中进行。区别在于模块至少具有一个导入/导出声明。为了克服这个问题,人们倾向于添加一个空的import语句,只是为了让TypeScript将您的文件视为模块。类似于`import * as'typescript'中的ts。 (3认同)
  • 您还可以执行“导出{}”。 (3认同)
  • 是的 - 它将适用于 Node.js 的当前类型,因为它们将“NodeJS”命名空间声明为全局。但并不是每个图书馆都这样做,所以我认为最好建议通用的解决方案。 (2认同)

The*_*inn 18

1.创建.env文件

# Contents of .env file
AUTHENTICATION_API_URL="http://localhost:4000/login"
GRAPHQL_API_URL="http://localhost:4000/graphql"
Run Code Online (Sandbox Code Playgroud)

2.将.env文件转换成process.envdotenv

我们可以利用dotenv来设置特定于环境的process.env变量。config.ts在您的src/目录中创建一个名为的文件并按如下方式填充:

// Contents of src/config.ts

import {config as configDotenv} from 'dotenv'
import {resolve} from 'path'

switch(process.env.NODE_ENV) {
  case "development":
    console.log("Environment is 'development'")
    configDotenv({
      path: resolve(__dirname, "../.env.development")
    })
    break
  case "test":
    configDotenv({
      path: resolve(__dirname, "../.env.test")
    })
    break
  // Add 'staging' and 'production' cases here as well!
  default:
    throw new Error(`'NODE_ENV' ${process.env.NODE_ENV} is not handled!`)
}
Run Code Online (Sandbox Code Playgroud)

注意: 此文件需要通过 import './config'放置在所有其他导入之前导入您的最顶层文件,可能是您的 src/index.ts

3. 检查 ENV 变量并定义 IProcessEnv

结合上述几种方法后,我们可以添加一些运行时检查以确保我们声明的IProcessEnv接口反映了我们.env.*文件中设置的 ENV 变量。下面的内容也可以在src/config.ts

// More content in config.ts
const throwIfNot = function<T, K extends keyof T>(obj: Partial<T>, prop: K, msg?: string): T[K] {
  if(obj[prop] === undefined || obj[prop] === null){
    throw new Error(msg || `Environment is missing variable ${prop}`)
  } else {
    return obj[prop] as T[K]
  }
}
// Validate that we have our expected ENV variables defined!
['AUTHENTICATION_API_URL', 'GRAPHQL_API_URL'].forEach(v => {
  throwIfNot(process.env, v)
})

export interface IProcessEnv {
  AUTHENTICATION_API_URL: string
  GRAPHQL_API_URL: string
}

declare global {
  namespace NodeJS {
    interface ProcessEnv extends IProcessEnv { }
  }
}
   
Run Code Online (Sandbox Code Playgroud)

这将为我们提供适当的 IntelliSense/tslint 类型检查,以及在部署到各种环境时的一些理智。

请注意,这也适用于 ReactJS 应用程序(NodeJS服务器应用程序相反)。您可以省略步骤 (2),因为这是由 处理的create-react-app


Dav*_*mer 15

我知道这会帮助那些搜索此内容但找不到简单答案的人,为什么你的proccess.env变量会让你的编译器发出呜呜声:

安装@types/node:

npm i @types/node
Run Code Online (Sandbox Code Playgroud)

然后,无论您将 env 作为字符串包含在何处,请执行以下操作:

process.env.YOUR_ENV ?? ''
Run Code Online (Sandbox Code Playgroud)

双问号允许您检查空/未定义。


Joe*_*lay 12

无法保证在Node进程中有什么(如果有的话)环境变量可用 - NODE_ENV变量只是一个由Express推广的约定,而不是内置于Node本身的内容.因此,将它包含在类型定义中是没有意义的.相反,他们定义process.env如下:

export interface ProcessEnv {
    [key: string]: string | undefined
}
Run Code Online (Sandbox Code Playgroud)

这意味着process.env可以使用字符串索引以获取字符串(或者undefined,如果未设置变量).要修复错误,您必须使用索引语法:

let env = process.env["NODE_ENV"];
Run Code Online (Sandbox Code Playgroud)

或者,正如jcalz在评论中指出的那样,如果您使用的是TypeScript 2.2或更高版本,则可以使用点语法访问类似上面定义的索引类型 - 在这种情况下,您的代码应该按原样工作.

  • 借助此处已接受的答案来提及 env-var,这是我编写的一个模块。它将从 process.env 读取变量,并将它们从 *string* 强制转换为您需要的正确类型,例如 *number*。使用 TypeScript 2.2,您显然不需要它,但它使 process.env 的使用更加清晰。 (2认同)

hai*_*ive 10

只需在使用前添加process.env.NODE_ENV以下行:

declare var process : {
  env: {
    NODE_ENV: string
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么会这样,但谢谢!我采用了一个更通用的解决方案,如`declare var process: { env: { [key: string]: string; } };` (3认同)
  • @Shakeel 这是因为声明合并而有效:https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation (2认同)

Pet*_*r W 10

这是一个简短的函数,它保证将 process.env 值作为字符串提取——否则会抛出错误。

对于更强大(但也更大)的东西,这里的其他人建议使用env-var

/**
 * Returns value stored in environment variable with the given `name`.
 * Throws Error if no such variable or if variable undefined; thus ensuring type-safety.
 * @param name - name of variable to fetch from this process's environment.
 */
export function env(name: string): string {
  const value = process.env[name];

  if (!value) {
    throw new Error(`Missing: process.env['${name}'].`);
  }

  return value;
}
Run Code Online (Sandbox Code Playgroud)

然后,您应该能够编写如下代码:

let currentEnvironment: string;
currentEnvironment = env('NODE_ENV');
Run Code Online (Sandbox Code Playgroud)

  • 漂亮又干净,值得赞赏。 (3认同)

Ery*_*ing 8

对我有用的是,在我想使用的任何地方,process.env我首先导入dotenv并调用config()它。另外,请记住在末尾追加!并确保在您的.env文件中定义了该属性

import dotenv from 'dotenv';

dotenv.config();

export const YOUR_ATTRIBUTE = process.env.YOUR_ATTRIBUTE!;
Run Code Online (Sandbox Code Playgroud)

  • @VadimSheremetov !用于告诉编译器该值不会是未定义的。例如,变量的类型可以是“字符串|未定义|空”。如果您尝试分配此变量,编译器会抱怨该值可能为 null 或未定义,因此通过添加 ! 您告诉编译器忽略或删除该检查,因为您已经承担了责任并将确保该值不是未定义的。所以 typescript 不会对你大喊大叫,你可以轻松地运行你的程序。希望这有帮助 (4认同)
  • 这个“!”是什么意思?标志究竟如何呢? (3认同)

Muh*_*raf 8

  1. 通过运行安装@types/nodenpm i @types/node
  2. 添加"types": [ "node" ]到 tsconfig.json 文件中的compilerOptions部分。


fey*_*diz 8

创建一个类似 global.d.ts 的文件

\n
\ndeclare global {\n  namespace NodeJS {\n    interface ProcessEnv {\n      SECRET: string;\n    }\n  }\n}\nexport {};\n\n
Run Code Online (Sandbox Code Playgroud)\n

教程由 Christian H\xc3\xb6ller 提供

\n


pwx*_*coo 5

使用打字稿最新版本执行后:

npm install --save @types/node

您可以process.env直接使用。

console.log(process.env["NODE_ENV"])

如果已设置,您将看到预期的结果NODE_ENV


Vil*_*lle 5

您可以为此使用类型断言

有时,您会遇到比TypeScript更了解值的情况。通常,当您知道某个实体的类型可能比其当前类型更具体时,就会发生这种情况。

类型断言是一种告诉编译器“相信我,我知道我在做什么”的方法。类型断言就像其他语言中的类型转换一样,但是不执行任何特殊的数据检查或重构。它对运行时间没有影响,仅由编译器使用。TypeScript假定您(程序员)已经执行了所需的任何特殊检查。

const nodeEnv: string = (process.env.NODE_ENV as string);
console.log(nodeEnv);
Run Code Online (Sandbox Code Playgroud)

另外,您可能会发现像env-var这样的库更适合此特定目的-

“使用正确的类型加载和清理node.js中的环境变量的解决方案”

  • 这是最好的答案。谢谢! (2认同)