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: