How to use node-config in typescript?
Solution 1
config.get
utility can be used to get the config values like so:
import config from 'config';
const port: number = config.get('server.port');
Solution 2
I'm taking a slightly different approach - defining the variables in JavaScript, and accessing them in TypeScript.
Using the following folder structure:
├── config
│ ├── custom-environment-variables.js
│ ├── default.js
│ ├── development.js
│ └── production.js
└── server
├── config.ts
└── main.ts
I define the configuration in the root config/
folder. For example:
// config/default.js
module.exports = {
cache: false,
port: undefined // Setting to undefined ensures the environment config must define it
};
// config/development.js
module.exports = {
port: '3000'
}
// config/production.js
module.exports = {
cache: true
}
// config/custom-environment-variables.js
module.exports = {
port: 'PORT'
}
Now, in TypeScript land, I define an interface to provide nicer autocomplete & documentation, and write some bridging code to pull in the config from node-config
into my config map:
// server/config.ts
import nodeConfig from 'config';
interface Config {
/** Whether assets should be cached or not. */
cache: boolean;
/** The port that the express server should bind to. */
port: string;
}
const config: Config = {
cache: nodeConfig.get<boolean>('cache'),
port: nodeConfig.get<string>('port')
};
export default config;
Finally, I can now import and use my config variables inside any TypeScript code.
// server/main.ts
import express from 'express';
import config from './config';
const { port } = config;
const app = express();
app.listen(port);
This approach has the following benefits:
- We can use the rich and battle-tested features available from
node-config
without needing to re-invent the wheel - We have a strongly-typed, well documented config map which can be imported and used from anywhere inside our TS code
Solution 3
Use this "import * as config from 'config';" instead of "import config from 'config';"
import * as config from 'config';
const port = config.get('server.port');
console.log('port', port);
// port 4000
config/development.json
{
"server": {
"port": 4000
}
}
and set NODE_ENV=development
export NODE_ENV=development
note: No need this NODE_ENV set if you use default
Solution 4
From the previous, I was still having trouble where config
was not able to find the server
key from default.ts
.
Below is how I am using npm config module. Updated export default {
to export =
:
// default.ts
export = {
server: {
port: 4000,
},
logLevel: 'error',
};
Usage within the app [Same]:
import config from 'config';
console.log(config.get('server'));
Solution 5
I use IConfig
interface, so I can set the config path first:
import { IConfig } from 'config';
export function dosomething() {
process.env["NODE_CONFIG_DIR"] = 'path to config dir';
//using get
const config: IConfig = require("config");
const port = config.get('server.port');
console.log('port', port);
//using custom schema
const config2: { server: { port: number } } = require("config");
console.log('config2.server.port', config2.server.port);
}
//port 4000
//config2.server.port 4000
Related videos on Youtube
Deepak
Updated on September 16, 2022Comments
-
Deepak over 1 year
After installing
node-config
and@types/config
:yarn add config yarn add --dev @types/config
And adding config as described in lorenwest/node-config:
// default.ts export default { server: { port: 4000, }, logLevel: 'error', };
When I am trying to use in my app:
import config from 'config'; console.log(config.server);
I am getting the error:
src/app.ts(19,53): error TS2339: Property 'server' does not exist on type 'IConfig'.
-
Deepak almost 6 yearsIt is just a workaround. still looking for better answer.
-
Estus Flask almost 6 yearsThis is how config is expected to be used.
get
andhas
are actual reasons to use it. It provides too much magic to be properly typed. You could extend its type likeconst config: IConfig & MySchema = require('config')
or with custom d.ts typing, but you cannot be sure that expected properties are there because they can exist in one config but not in another. -
Fedoranimus over 4 yearsNot sure what a "better answer" would look like, but it's important to note that
config.get()
supports generics. You could doconfig.get<number>('server.port')
and that might be a little cleaner in some instances. -
Ernest Jones about 2 years
-
Emmanuel Meric de Bellefon almost 2 yearsautomatic typing could be certainly implemented in the library using ts template litterals