Last updated: Feb 29, 2024
Reading timeยท3 min

To define types for process.env in TypeScript:
environment.d.ts file and declare types in the global namespace.ProcessEnv interface.export {}.In the src directory of your project, create a types directory containing
the following environment.d.ts file.
export {}; declare global { namespace NodeJS { interface ProcessEnv { DB_PORT: number; DB_USER: string; ENV: 'test' | 'dev' | 'prod'; } } }
The example shows how to add typings for the DB_PORT, DB_USER and ENV
properties on the process.env object.
Now I can access the properties on the process.env object and get
auto-completion.
console.log(process.env.DB_USER); console.log(process.env.ENV); console.log(process.env.DB_PORT);

However, their values are undefined right now because we haven't set up a
.env file yet.
types to the typeRoots arrayIf you've tried restarting your IDE and still don't get autocompletion for the
specified properties on the process.env object, try adding the path to your
types directory to your
tsconfig.json file.
{ "compilerOptions": { // ... rest "typeRoots": ["./node_modules/@types", "./src/types"] } }
We used the export {} line in our environment.d.ts file to mark it as an
external module.
A module is a file that contains at least 1 import or export statement. We
are required to do that to be able to augment the global scope.
.d.ts files in the same places it looks for your regular .ts files. The location is determined by the include and exclude settings in your tsconfig.json file.dotenv packageTo add values for the specified properties on the process.env object, we need
to install the dotenv package.
Open your terminal in the root directory of your project and run the following commands.
npm install dotenv npm install -D @types/node
Now create a .env file in the root directory of your project.
DB_PORT=9999 DB_USER=bobby_hadz ENV=test
.env file to your .gitignore, especially if you work on a public repository.In your index.ts file, before importing anything else, import and initialize
the dotenv package.
import 'dotenv/config'; console.log(process.env.DB_USER); // ๐๏ธ "bobby_hadz" console.log(process.env.ENV); // ๐๏ธ "test" console.log(process.env.DB_PORT); // ๐๏ธ "9999"

dotenv package as the first thing in your index.ts file, especially if you have other files that need to access the environment variables.If you import another file before initializing dotenv, you end up running the
files before the properties are set on the process.env object.
Now restart your development server and you should see the properties on the
process.env object print out the specified values.

DB_PORT property has a value of type string, even though we set it as a number in the .env file.If you aren't sure whether a specific property on the process.env object will
be populated, mark it as optional.
export {}; declare global { namespace NodeJS { interface ProcessEnv { DB_PORT?: number; // ๐๏ธ mark optional DB_USER: string; ENV: 'test' | 'dev' | 'prod'; } } }
We marked the DB_PORT property as
optional
using a question mark.
This means that it will either be of the specified type or be undefined.
This is useful when you want to have to check if the property exists before you perform an operation in your code.
console.log(process.env.DB_PORT || ''); // ๐๏ธ "9999" or '', but not undefined
If you try to access a built-in method on an undefined value, you'd get a
runtime error, so it's best to use optional properties when we aren't sure the
property will be set.
You can learn more about the related topics by checking out the following tutorials: