Environment variables are a crucial part of many applications, providing a way to store and manage sensitive information and configuration settings. In TypeScript, you often need to access environment variables from the process.env object provided by Node.js. However, since process.env is an object with string keys and values, it lacks type information, making it harder to work with in a type-safe manner. In this article, we will explore various techniques for handling process environment variables in TypeScript and provide code samples to illustrate each method. Let's get started!

1,  Using Type Assertions

The simplest way to access environment variables in TypeScript is to use type assertions. This approach allows you to specify the expected type of an environment variable, providing additional type information to the TypeScript compiler.

const databaseUrl = process.env.DATABASE_URL as string;

console.log(databaseUrl); // Output: the value of the DATABASE_URL environment variable

2,  Creating a Typed Configuration Object

A better approach to handling environment variables in TypeScript is to create a typed configuration object that maps environment variables to their respective types. This method provides a type-safe way to access environment variables throughout your application.

interface AppConfig {
  port: number;
  databaseUrl: string;
  secretKey: string;
}

const config: AppConfig = {
  port: parseInt(process.env.PORT as string, 10),
  databaseUrl: process.env.DATABASE_URL as string,
  secretKey: process.env.SECRET_KEY as string,
};

console.log(config.port); // Output: the value of the PORT environment variable as a number

3,  Using Type Guards

Type guards are a powerful feature in TypeScript that allows you to narrow down the type of a variable within a specific scope. By creating custom type guards for environment variables, you can ensure their presence and correct type at runtime.

function isString(value: unknown): value is string {
  return typeof value === "string";
}

function getEnvString(key: string): string {
  const value = process.env[key];

  if (!isString(value)) {
    throw new Error(`Environment variable '${key}' is missing or not a string`);
  }

  return value;
}

const apiUrl = getEnvString("API_URL");
console.log(apiUrl); // Output: the value of the API_URL environment variable

4,  Using a Configuration Library

To simplify working with environment variables in TypeScript, you can use a configuration library like dotenv to load environment variables from a .env file and dotenv-safe to validate their presence and type.

First, install the required packages:

npm install dotenv dotenv-safe

Create a .env.example file with the required environment variables and their types:

# .env.example
PORT=number
API_KEY=string

Create a .env file with the actual environment variable values:

# .env
PORT=3000
API_KEY=myapikey

Now, use the dotenv and dotenv-safe libraries to load and validate the environment variables in your TypeScript application:

import * as dotenv from "dotenv";
import * as dotenvSafe from "dotenv-safe";

dotenvSafe.config();

const port = parseInt(process.env.PORT as string, 10);
const apiKey = process.env.API_KEY as string;

console.log(port); // Output: the value of the PORT environment variable as a number
console.log(apiKey); // Output: the value of the API_KEY environment variable

Conclusion

In this article, we covered various techniques for handling process environment variables in TypeScript, such as using type assertions, creating typed configuration objects, using type guards, and leveraging configuration libraries like dotenv and dotenv-safe. By understanding these techniques, you can efficiently access and manage environment variables in a type-safe manner, improving the overall quality and maintainability of your TypeScript applications.

Whether you're building a web application that relies on sensitive information, such as API keys and database credentials, or you need to manage configuration settings for different environments, handling process environment variables in TypeScript is an essential skill. With the methods discussed in this blog, you can now confidently manage environment variables in your TypeScript projects while maintaining the benefits of type safety and ensuring that your applications are both robust and maintainable.

If you are interested in similar posts, take a look at my home page to find similar articles.