25

process.env is of type ProcessEnv with this definition:

export interface ProcessEnv {
    [key: string]: string | undefined;
}

I'd like to augment this TypeScript interface so that it contains the keys specific to my app, so that the result is something like:

export interface ProcessEnv {
    MY_VARIABLE_1: string;
    MY_OTHER_VARIABLE: string;
    [key: string]: string | undefined;
}

I cannot find a way to do it, I guess it will be declare module or declare namespace somewhere but cannot find a specific way to achieve this.

5
  • Why do you need such typing ? For autocomplete or verification ? For autocomplete your example should work just fine. For verification - your extra fileds do not make [key:string]:string any more specific. Commented Oct 30, 2017 at 6:11
  • 1
    It's for autocompletion. (Augmentation can only add to interfaces, not remove from them, so the indexer will always be there.) Commented Oct 30, 2017 at 7:21
  • So what is your question then? How to redefine a type from third-party library ? Have you tried using as ? Or you want a cleaner solution ? Commented Nov 1, 2017 at 3:23
  • 1
    The question is how to write augmentation (I guess declare namespace ...) so that when I do process.env., the IDE suggests my custom variables. Commented Nov 1, 2017 at 8:25
  • stackoverflow.com/questions/37398009/… Commented Nov 6, 2017 at 2:13

3 Answers 3

45

The ProcessEnv must be inside the namespace NodeJS and doesn't need to declare the [key: string]: string | undefined;, it inherits from the initial ProccessEnv.

declare namespace NodeJS {
  export interface ProcessEnv {
    MY_VARIABLE_1: string;
    MY_OTHER_VARIABLE: string;
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Is there a way to remove the [key: string]: string | undefined indexer? It's too permissive for me; I could still fat-finger something.
If you don't remove the default declaration ([key: string]: string | undefined), then it doesn't make sense to extend process.env. (1) Anything you add to process.env but don't declare will be accepted (string: string) and (2) anything you declare has to be string, or else it will clash with the [key: string]: string | undefined rule. Besides, even without Typescript, anything you add to process.env will be type string. Conclusion: don't worry about extending process.env, just make sure to document and include the variables in your code - the current type declaration is fine.
you can remove the [key:string] from the original .d.ts (not recommended, but one option). But better than that, what I do is JSDoc the real variables so that at least you can confirm you're using the right thing by hovering the mouse and seeing its description.
Just discovered you can remove the indexer by changing interface to type.
7

without export {} doesn't work for me (Next 14.0.4), this is what works:

// environment.d.ts
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      DATABASE_URL: string;
      NEXT_PUBLIC_GOOGLE_CLIENT_ID: string;
    }
  }
}

export {}; // add here

Comments

1

If you want to remove the [key: string]: string | undefined indexer from process.env declaration and thus restrict the use of env to explicitly declared names, you can declare process as variable (in some of your *.ts files):

declare var process : {
  env: {
    NODE_ENV: string
  }
}

2 Comments

Where do I need to do this?
In some of your *.ts files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.