Environment Variables in TypeScript
In software development, environment variables allow you to define values that can change based on the environment your application is running in. For instance, you might have a different database connection string for development and production. TypeScript, being a superset of JavaScript, can make use of environment variables. This guide will help you understand how to work with them effectively.
Introduction to Environment Variables
Environment variables are key-value pairs that can affect how running processes behave on a computer. They're especially useful in the following scenarios:
- Switching between development and production configurations.
- Storing secrets that shouldn't be hardcoded.
- Customizing behavior without modifying code.
Accessing Environment Variables
In Node.js (and by extension, TypeScript running in a Node environment), you can access environment variables using process.env
.
const dbName = process.env.DATABASE_NAME;
Setting Environment Variables
Manually Setting
You can set environment variables directly in the terminal:
-
Unix-based systems (Linux & macOS):
export DATABASE_NAME=my_database
-
Windows:
set DATABASE_NAME=my_database
Using .env
Files
A common practice is to store environment variables in a .env
file.
Install the dotenv
package to help load these variables:
npm install dotenv
Create a .env
file in the root of your project:
DATABASE_NAME=my_database
Load the .env
file in your TypeScript code:
import * as dotenv from 'dotenv'; dotenv.config(); const dbName = process.env.DATABASE_NAME;
Strong Typing Environment Variables
To leverage TypeScript's static typing with environment variables, you can define types for them.
interface Env { DATABASE_NAME: string; DATABASE_PORT?: number; } const myEnv: Env = { DATABASE_NAME: process.env.DATABASE_NAME || '', DATABASE_PORT: process.env.DATABASE_PORT ? parseInt(process.env.DATABASE_PORT) : undefined };
Type Safety with Type Guards
Ensure the presence and validity of specific environment variables using type guards:
if (!process.env.DATABASE_NAME) { throw new Error("DATABASE_NAME is not defined"); } if (process.env.DATABASE_PORT && isNaN(Number(process.env.DATABASE_PORT))) { throw new Error("DATABASE_PORT should be a number"); }
Using with Frontend Projects
If you're using TypeScript with frontend frameworks like React or Angular, bundlers like Webpack or Parcel might inline environment variables during the build process.
For example, with create-react-app
, you can prefix environment variables with REACT_APP_
to make them available in your app:
REACT_APP_API_ENDPOINT=https://api.example.com
Then in your TypeScript:
const apiEndpoint = process.env.REACT_APP_API_ENDPOINT;
Note: Be cautious about which environment variables you expose to the frontend. Never expose sensitive data like API keys or secrets.
Tips and Best Practices
- Default values: Provide default values for your environment variables to ensure your application behaves predictably.
- Separate configs: Use different
.env
files for different environments, e.g.,.env.development
and.env.production
. - Secrets: Never commit
.env
files containing secrets to version control. Add.env
to.gitignore
.
Further Reading
With this knowledge, you can effectively leverage environment variables in your TypeScript projects, making your applications more flexible and environment-aware.
Invite only
Fast. Opinionated. Collaborative. Local-first. Keyboard centric. Crafted to the last pixel. We've got 50 slots for Alpha access.
How to turn webpages into editable canvases with a JavaScript bookmarklet
Kris Lachance
How to fix the "not all code paths return a value" issue in TypeScript
Kris Lachance
Working with WebSockets in Node.js using TypeScript
Kris Lachance
Type Annotations Can Only Be Used in TypeScript Files
Kris Lachance
Guide to TypeScript Recursive Type
Kris Lachance
How to Configure Knex.js with TypeScript
Kris Lachance