typescript and create-react-app .env

Louis ❤️ ☮ ✋
3 min readJul 26, 2019

--

You can create a type definition file that extends the NodeJS namespace to enable auto-completion for your env configuration. This is quite useful if you plan to reduce the amount of time spent looking up your .env file:

Auto Completion for your process.env!

Check bottom for the solution. For now, let’s wander back a bit. I first thought about this problem when I found that process.env.NODE_ENV is typed and has code completion, while the other does not:

NODE_ENV has code completion.

This piece of information had been in my mind since the first time I saw it around 2017. However, I never really looked into it too deeply as back then I had no need to leverage client-side environment variable.

At roshub.io, we decided to leverage client-side environment to swap between staging and production endpoints. Initially with 2 variables it was manageable. But when that number grew to 13, it became a bit annoying to lookup the .env file, as the variable names are increasingly getting longer. This annoyance can be tolerated for a while, as we were focusing on our product. However, in the back of my mind, there was a strong drive to squash this “bug.”

Technically this is not a bug, that is why there were "”.

A big win of using TypeScript is that refactor is a breeze, and that is the key to move fast — starting with one file, grow it to split it into several files when it gets complex, so on, so forth. This applies to our type definition as well, as using single .d (definition) file to describe both api typing as well as our theme typing was too much. So we decided to finally split our typing into these neat files:

typings

And I removed the good ol’ react-app-env.d.ts file. Much to my surprise, when running CRA (create-react-app) server afterward, the file was resurrected. I thought Dr. Manhattan was behind me for 5 seconds, then reality came back to me: react-scripts (the main program powering CRA) was programmed to generate the file.

This is when my brain started to notice the name of this file: react-app-env. Every magic string has meaning, said the basic rule of edb (on Windows you can use x64dbg). To generate a file with such specific name means there was some significant use of it, probably within the organization of ${process.env.REACT_APP_AUTHOR}.

Digging deeper with duckduckgo.com with the search term “react-app-env.d.ts declare global,” the third result (note: not 1st or 2nd, but 3rd) gave some great insight, in particular, in this comment.

In case the github link got spike traffic

The original issue was basically the trying to tackle the “bug” at hand, and the code snippet was extremely insightful:

declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production' | 'test'
PUBLIC_URL: string
}
}

In brief, the typescripts support of CRA consume an extended definition under the NodeJS namespace. To extend it for our environment, simply put the snippet above in our react-app-env.d.ts and it’s Q.E.D

BONUS

You now know how to extends your environment typing for some good old lazy process.envauto-completion. But now you need to deal with global API placed under Window (like Stripe.js). Below will save you a trip to the duck (This is a modified version of our react-app-env.d.ts file:

/// <reference types="react-scripts" />declare namespace NodeJS {interface ProcessEnv {    NODE_ENV: 'development' | 'production' | 'test'    PUBLIC_URL: string    REACT_APP_HASH: string    REACT_APP_API_URI: string    REACT_APP_WS_URI: string    }}interface Window {    Stripe: any}

--

--

Louis ❤️ ☮ ✋

Creative writer who became a robotic developer. Co-founder and Head of Product https://roshub.io