typescript and create-react-app .env
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:
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:
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:
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.
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.env
auto-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}