Achieve Type-safe Environment Variables with “t3-env”

Environmental variables can often be a source of frustration when developing an application. By convention, they’re not checked into version control to prevent leaking secrets or other sensitive information. Personally, I find myself misremembering the exact variable names or even misspelling them. When new ones are added to a project, it must be communicated to the entire team, and everyone must update their respective .env files manually. When deploying an application after adding new ones, you must manually add them to the production environment. Failing to do so may cause hard-to-debug issues, which end up small but frustrating nonetheless. Because of this, a favorite library of mine is `t3-env`.

It allows you to define a Zod schema for your environmental variables, ensuring they are present and also of the correct type. As a bonus, you get autocompletion, which will help circumvent any misspelling or misremembering issues. t3-env comes in 3 flavors. Two supporting specific frameworks: Next.js and Nuxt, and also a framework-agnostic “core” module.

t3-env: An Example

To get started, install the npm package with:


npm install @t3-oss/env-core zod

Now, create an env.ts file in your ./src folder or equivalent. Here’s an example env.ts file:


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

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
  },
  clientPrefix: "PUBLIC_",
  client: {
	PUBLIC_MAPBOX_ACCESS_TOKEN: '....'
  }
});

Now you can write the following code and get autocompletion in your IDE as well as type safety. You can use it on the server:


import { env } from "~/env";
import { drizzle } from 'drizzle-orm/node-postgres';

export const db = drizzle(env.DATABASE_URL);

And on the client:


import { env } from "~/env";
import * as React from 'react';
import Map from 'react-map-gl/mapbox';

function App() {  
  return (    
    <Map      
      mapboxAccessToken={env.PUBLIC_MAPBOX_ACCESS_TOKEN}      
      initialViewState={{   
        longitude: -87.6457012,        
        latitude: 41.8843013,        
        zoom: 14     
      }}      
      style={{width: 600, height: 400}}      
      mapStyle="mapbox://styles/mapbox/streets-v9"    
    />  
  );
}

If neither of the above environment variables are present in your .env file, it will throw an error in your terminal, to tell you exactly which one is missing and the type it expects it to be in. Additionally, for client-side environment variables, it allows you to set a prefix for publicly exposed variable values. If you fail to use the prefix in your environment variables, it will throw an error.

Not A Perfect Solution

This method isn’t perfect: You still have to be sure to add the environment variables to your `.env` file. You still must inform your teammates of the new environment variables and share their values by some means. Missing environment variables could crash your entire application at best. At worst, it simply does not work correctly and causes undesired behaviors.

Having t3-env in your project will certainly help you avoid the headache of having an undefined variable at runtime and provide a tighter feedback loop for when a value is missing, and for that reason, I highly recommend you give this library a try.

 
Conversation

Join the conversation

Your email address will not be published. Required fields are marked *