【问题标题】:How to use node-config in typescript?如何在打字稿中使用节点配置?
【发布时间】:2018-11-21 15:22:02
【问题描述】:

安装node-config@types/config后:

yarn add config
yarn add --dev @types/config

并按照lorenwest/node-config 中所述添加配置:

// default.ts
export default {
  server: {
    port: 4000,
  },
  logLevel: 'error',
};

当我尝试在我的应用中使用时:

import config from 'config';

console.log(config.server);

我收到错误:

src/app.ts(19,53): error TS2339: Property 'server' does not exist on type 'IConfig'.

【问题讨论】:

    标签: node.js typescript node-config


    【解决方案1】:

    我可以完成这项工作的唯一方法是卸载 @types/config 并修改类型定义以包含我的配置文件。

    config.d.ts

        declare module 'config' {
        
          // Importing my config files
          import dev from '#config/development.json'
          import test from '#config/test.json'
          import prod from '#config/production.json'
        
          // Creating a union of my config
          type Config = typeof dev | typeof test | typeof prod
        
          var c: c.IConfig;
        
          namespace c {
        
            // see https://github.com/lorenwest/node-config/wiki/Using-Config-Utilities
            interface IUtil {
                // Extend an object (and any object it contains) with one or more objects (and objects contained in them).
                extendDeep(mergeInto: any, mergeFrom: any, depth?: number): any;
        
                // Return a deep copy of the specified object.
                cloneDeep(copyFrom: any, depth?: number): any;
        
                // Return true if two objects have equal contents.
                equalsDeep(object1: any, object2: any, dept?: number): boolean;
        
                // Returns an object containing all elements that differ between two objects.
                diffDeep(object1: any, object2: any, depth?: number): any;
        
                // Make a javascript object property immutable (assuring it cannot be changed from the current value).
                makeImmutable(object: any, propertyName?: string, propertyValue?: string): any;
        
                // Make an object property hidden so it doesn't appear when enumerating elements of the object.
                makeHidden(object: any, propertyName: string, propertyValue?: string): any;
        
                // Get the current value of a config environment variable
                getEnv(varName: string): string;
        
                // Return the config for the project based on directory param if not directory then return default one (config).
                loadFileConfigs(configDir?: string): any;
        
                // Return the sources for the configurations
                getConfigSources(): IConfigSource[];
                
                // Returns a new deep copy of the current config object, or any part of the config if provided.
                toObject(config?: any): any;
        
                /**
                 * This allows module developers to attach their configurations onto
                 * the 6 years agoInitial 0.4 checkin default configuration object so
                 * they can be configured by the consumers of the module.
                 */
                setModuleDefaults(moduleName:string, defaults:any): any;
            }
        
            interface IConfig {
                // Changed the get method definition.
                get<K extends keyof Config>(setting: K): Config[K];
                has(setting: string): boolean;
                util: IUtil;
            }
        
            interface IConfigSource {
                name: string;
                original?: string;
                parsed: any;
            }
          }
        
          export = c;
        
        }
    
    

    然后我可以这样做:

    【讨论】:

      【解决方案2】:

      您可以使用any 返回类型。

      const serverConfig: any = config.get('server');
      

      【讨论】:

        【解决方案3】:

        我采用了一种稍微不同的方法——在 JavaScript 中定义变量,并在 TypeScript 中访问它们。

        使用以下文件夹结构:

        ├── config
        │   ├── custom-environment-variables.js
        │   ├── default.js
        │   ├── development.js
        │   └── production.js
        └── server
            ├── config.ts
            └── main.ts
        

        我在根config/ 文件夹中定义配置。例如:

        // 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'
        }
        

        现在,在 TypeScript 领域,我定义了一个接口来提供更好的自动完成和文档,并编写一些桥接代码以将配置从 node-config 拉入我的配置映射:

        // 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;
        

        最后,我现在可以在任何 TypeScript 代码中导入和使用我的配置变量。

        // server/main.ts
        import express from 'express';
        import config from './config';
        
        const { port } = config;
        
        const app = express();
        
        app.listen(port);
        

        这种方法有以下好处:

        • 我们可以使用 node-config 提供的丰富且久经考验的功能,而无需重新发明轮子
        • 我们有一个强类型、有据可查的配置映射,可以从我们的 TS 代码中的任何位置导入和使用

        【讨论】:

          【解决方案4】:

          使用这个“import * as config from 'config';”而不是“从'config'导入配置;”

              import * as config from 'config';
          
              const port = config.get('server.port');
              console.log('port', port);
              // port 4000
          

          config/development.json

              {
                "server": {
                    "port": 4000
                }
              }
          

          并设置 NODE_ENV=development

           export NODE_ENV=development
          

          注意:如果使用默认设置,则不需要设置此 NODE_ENV

          【讨论】:

            【解决方案5】:

            从上一页开始,我仍然遇到问题,config 无法从 default.ts 找到 server 密钥。

            以下是我如何使用 npm 配置模块。将export default { 更新为export =

            // default.ts
            export = {
              server: {
                port: 4000,
              },
              logLevel: 'error',
            };
            

            在应用内使用[相同]:

            import config from 'config';
            
            console.log(config.get('server'));
            

            【讨论】:

              【解决方案6】:

              我使用IConfig接口,所以我可以先设置配置路径:

              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
              

              【讨论】:

                【解决方案7】:

                config.get 实用程序可用于获取配置值,如下所示:

                import config from 'config';
                
                const port: number = config.get('server.port');
                

                【讨论】:

                • 这只是一种解决方法。仍在寻找更好的答案。
                • 这是 config 的预期使用方式。 gethas 是使用它的实际原因。它提供了太多的魔力,无法正确输入。您可以扩展其类型,如 const config: IConfig &amp; MySchema = require('config') 或自定义 d.ts 类型,但您无法确定预期的属性是否存在,因为它们可以存在于一个配置中,但不能存在于另一个配置中。
                • 不确定“更好的答案”是什么样的,但重要的是要注意config.get() 支持泛型。您可以使用config.get&lt;number&gt;('server.port'),在某些情况下可能会更干净一些。
                猜你喜欢
                • 2018-12-17
                • 2022-10-18
                • 2021-12-05
                • 2017-01-17
                • 2022-01-05
                • 2014-07-07
                • 2018-04-10
                • 2017-02-21
                • 2019-01-02
                相关资源
                最近更新 更多