Backend Development 6 min read

How to Get TypeScript Autocomplete for process.env and Safely Validate Env Variables

This article explains why TypeScript’s process.env lacks autocomplete, shows three approaches—including global type augmentation, a custom getter function, and using t3‑env with Zod—to ensure environment variables are type‑safe and available at runtime.

Code Mala Tang
Code Mala Tang
Code Mala Tang
How to Get TypeScript Autocomplete for process.env and Safely Validate Env Variables

In TypeScript projects, process.env often does not provide autocomplete and is inferred as string | undefined , requiring explicit type conversion even when the variable is known to exist.

Three solutions are presented to address this issue.

Solution 1: Enhance Global Types

Extend the global NodeJS.ProcessEnv interface to include your custom environment variables.

<code>// globals.d.ts
namespace NodeJS {
  interface ProcessEnv {
    MY_ENV_VARIABLE: string;
  }
}
</code>

After this declaration merge, process.env.MY_ENV_VARIABLE is recognized as a string with autocomplete in every file.

Note that this does not guarantee the variable exists at runtime.

Solution 2: Encapsulate Access with a Getter

Create a utility function that reads and validates required variables, throwing an error if missing.

<code>const getEnv = (key: keyof NodeJS.ProcessEnv, defaultValue?: string): string => {
  const value = process.env[key];
  if (!value && !defaultValue) {
    throw new Error(`Environment variable ${key} is missing`);
  }
  return value || defaultValue!;
};

export const config = {
  apiUrl: getEnv('API_URL'),
  port: getEnv('PORT', '3000'),
  databaseUrl: getEnv('DATABASE_URL'),
};
</code>

This approach eliminates undefined cases, provides type safety, and validates variables when the application starts.

Solution 3: Use t3‑env with Zod for Runtime Validation

t3‑env, built on Zod, offers schema‑based validation of environment variables, ensuring type safety and correct formats.

Type safety through Zod definitions.

Runtime verification of required variables.

Environment isolation for development, production, etc.

<code>import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    OPEN_AI_API_KEY: z.string().min(1),
  },
  clientPrefix: "PUBLIC_",
  client: {
    PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
  },
  runtimeEnv: process.env,
});
</code>

If any variable is missing or fails its Zod schema, the application throws a detailed error at startup.

Custom validation rules can also be defined, for example ensuring API_TIMEOUT is a number between 1 and 10:

<code>export const customSchema = z.object({
  API_TIMEOUT: z.string().transform(Number).refine(val => val >= 1 && val <= 10, {
    message: "API_TIMEOUT must be between 1 and 10",
  }),
});
</code>

Which Solution to Choose?

If the project is small and you prefer not to add extra dependencies, enhancing the global type is a quick fix.

For larger projects or when you need guaranteed runtime presence of variables, using t3‑env with Zod provides robust validation.

TypeScriptNode.jsType SafetyZodEnvironment Variablest3-env
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.