Typing process.env and dealing with NODE_ENV
Tags: typescript, node, processenv, tutorial
Published: 2019-11-01 06:45:35

---
title: Typing process.env and dealing with NODE_ENV
published: true
description: Typing process.env 👨‍🍳
tags: typescript, node, process.env, tutorial
---
I don't know about you but I hate using process.env, it's like drunk typescript: *"process.env.blah.indeed().next().var ? Yeah dude, let's party 😛"*.

Well drunk typescript kinda sucks. Let's fix that 👨‍🍳

## TLDR;
### Install node typings
```bash
$ npm install --save @types/node
```

### Extend node typings (.d.ts file version)
```typescript
// someDefinitionFile.d.ts

// Target the module containing the `ProcessEnv` interface
// https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
declare namespace NodeJS
{

    // Merge the existing `ProcessEnv` definition with ours
    // https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces
    export interface ProcessEnv
    {
        NODE_ENV: "development" | "production" | "test";
        MY_API_KEY: string
        DB_USER?: string
        // ...
    }
}

```

### Extend node typings (.ts file version)
```typescript
// someFile.ts

// Required when adding declarations inside a module (.ts, not .d.ts)
// If you have documentation about why this is required I would love to know 🤓
declare global
{
    // Target the module containing the `ProcessEnv` interface
    // https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
    namespace NodeJS
    {
        // Merge the existing `ProcessEnv` definition with ours
        // https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces
        export interface ProcessEnv
        {
            NODE_ENV: "development" | "production" | "test";
            MY_API_KEY: string
            DB_USER?: string
            // ...
        }
    }
}

```

### Done
Yup, that's it 🤗

## Bonus tip, deal with `if( process.env.NODE_ENV === "something" )`
So now we've can define what values `process.env.NODE_ENV` can have (no more "is it dev or development..?" 😌). 

Usually we use that to do stuff like `if (process.env.NODE_ENV === "development")` with type safety.

That totally works, but what we really want to express is usually: `do that in dev only` or `unless in prod, do that`. 

Here's a simple way to make that more obvious in your codebase:

```typescript
const isProd = () => process.env.NODE_ENV === "production" || process.env.NODE_ENV === "staging" // Production here is a concept, not a value, for you it might include staging 

const isDev = () => !isProd()

export const devOnly = (action: () => void) => 
        isDev()  ?          
        action() :
        null


export const prodOnly = (action: () => void) => 
        isProd() ?          
        action() :
        null

export const unlessProd = (action: () => void) => 
        !isProd() ?          
        action()  :
        null


export const unlessDev = (action: () => void) => 
        !isDev() ?          
        action() :
        null

devOnly(()=> console.log("We're in dev mode 🥳"))
```
Same thing for the 0 duplication guys 😉
```typescript
type validator = () => boolean

type action    = () => void

const doIf = (condition: validator) =>
    (action: action) => 
        condition()  ?          
        action() :
        null

const not = (condition: validator) =>
 () => !condition()

const isProd = () => process.env.NODE_ENV === "production" || process.env.NODE_ENV === "staging" 

const isDev = not(isProd)

export const devOnly    = doIf(isDev)
export const prodOnly   = doIf(isProd)
export const unlessProd = doIf(not(isProd))
export const unlessDev  = doIf(not(isDev))
// ... testOnly, QA only, etc

devOnly(()=> console.log("We're in dev mode 🥳"))
```


## Going further 
Extending existing definitions is called [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces)


What we've done is called [Module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)

## Keep In Touch
You disagree, you have questions, something doesn't feel right, let's chat! Leave a comment or reach me via [Twitter](https://twitter.com/isthatcentered) or [Linkedin](https://www.linkedin.com/in/edouard-penin-526535b0/)