node-config has been serving the Node.js community as pretty much the default config solution for many years. Its simplistic, yet powerful design helped it to spread like a virus across multiple JS libraries. Yet those very design choices don’t always play nice with new strictly-typed kids on the block. Like TypeScript. How could we keep using our favorite config tool and stay on the type-safe side of things?

Step 1: Make an interface for your config

Supposedly, you have a config folder somewhere in your project, which in the most simple case has this structure:

default.ts

production.ts

Yes, node-config speaks TypeScript out-of-the-box!

Let’s consider a case of writing a config for an app, which creates new worlds populated only by cats.

Our default config could look like this:

Our production config could be this:

Basically, our production config is always a subset of our default one. So we could create an interface for our default config and use a partial (DeepPartial to be true) of that interface for our production config.

Let’s add constraint.ts file with the interface:

Then we could use it in our default.ts :

And in our production.ts :

Step 2: Make config.get type-safe

So far we resolved any inconsistencies between a variety of our configs. But config.get still returns any .

To fix that let’s add another typed version of config.get to its prototype.

Assuming your projects has the folder config in its root and the code of your app in the folder src , let's create a new file at src/config.service.ts

Now we can use config.getTyped anywhere in our app, importing it from src/config.service .

Be aware, we no longer can do caonfig.getTyped('cat.pawsNum') . It's impossible to make it type-safe. To make import config from 'config' work set "esModuleInterop":true under compilerOptions in your tsconfig.json .

It could look like this in our src/app.ts :

Live demo

You might want to use tsconfig-paths to avoid deep relative imports.

Hopefully, you’ve found something useful for your project. Feel free to communicate your feedback to me! I most certainly appreciate any criticism and questions.