@coast/nest-typed-config

中文文档
4.0.0发布于 2026/10/28MITTypeScript近 30 天下载 8960

Nest 框架的直观、类型安全配置模块

中文使用文档
文档目录25 节
  1. 不再写字符串来读取配置 .
  2. 特征
  3. 安装
  4. 灵感
  5. 快速启动
  6. 使用装载器
  7. 使用 dotenv 加载器
  8. 使用文件加载器
  9. 使用目录加载器
  10. 使用远程加载器
  11. 使用多加载器
  12. 使用自定义装入器
  13. 可变替代品的使用
  14. 默认值
  15. 转换原始配置
  16. 自定义获取器
  17. 多个外观
  18. 自定义验证函数
  19. 使用 Nest 的 IoC 容器外的配置( 装饰器中的用户)
  20. 小心点!
  21. 怎么样
  22. API 密码
  23. 更改日志
  24. 许可证
  25. 恒星历史

网纹图解

不再写字符串来读取配置 .

NPM Version Package License NPM Downloads build Coverage

特征

  • 提供一个安全且直观的配置方式 鸟巢 工程,和请求的 DTO 一样平滑 .
  • 用环境变量、json/yaml/toml配置文件或远程端点来装入您的配置 .
  • 验证您的配置 类验证器 财务报告和审定财务报表 类转换器。 。 。 .
  • 默认情况下提供方便使用选项, 而所有选项都是自定义的 .

安装

$ npm i --save nest-typed-config

Nest-typed-config 将默认安装所有加载者的依赖性。 如果你关心依赖大小和靴子时间,请退房 跳过可选依赖的指南。 。 。 .

灵感

有各种流行的配置模块 巢穴框架,例如 正式配置模块, (中文(简体) ), 巢状配置 财务报告和审定财务报表 巢状- 容易配置。这些模块可以帮助管理配置,验证它们,并通过 ConfigService但正是这时候 类型的安全就消失了。 例如:

// @nestjs/config, with type-casting
const dbUser = this.configService.get<string>('DATABASE_USER');
// nestjs-config, returns `any` type
const env = this.config.get('app.environment');
// nestjs-easyconfig, only string is supported
const value = this.config.get('key');

写作类型铸造是一种痛苦和难以维护,在现实世界的项目中常用非字符串配置. 该模块旨在提供直观和类型安全的方式来加载,验证和使用配置. 只要导入任何配置模型,并注入完整的TypeScript支持. 简言之:

// config.ts
export class Config {
  @IsString()
  public readonly host!: string;

  @IsNumber()
  public readonly port!: number;
}

// app.service.ts
import { Config } from './config';

@Injectable()
export class AppService {
  constructor(private readonly config: Config) {}

  show() {
    console.log(`http://${this.config.host}:${this.config.port}`);
  }
}

快速启动

先定义配置模型. 其巢可被任意地入入地.

// config.ts
import { Allow, ValidateNested } from 'class-validator';

// validator is omitted for simplicity
export class TableConfig {
  @Allow()
  public readonly name!: string;
}

export class DatabaseConfig {
  @Type(() => TableConfig)
  @ValidateNested()
  public readonly table!: TableConfig;
}

export class RootConfig {
  @Type(() => DatabaseConfig)
  @ValidateNested()
  public readonly database!: DatabaseConfig;
}

然后,添加一个配置文件,例如 .env.yaml 在项目根目录中 :

database:
  table:
    name: example

创建配置文件后导入 TypedConfigModule 财务报告和审定财务报表 fileLoader 从文件系统装入配置.

// app.module.ts
import { Module } from '@nestjs/common';
import { TypedConfigModule, fileLoader } from 'nest-typed-config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { RootConfig } from './config';

// Register TypedConfigModule
@Module({
  imports: [
    TypedConfigModule.forRoot({
      schema: RootConfig,
      load: fileLoader(),
    }),
  ],
  providers: [AppService],
  controllers: [AppController],
})
export class AppModule {}

就这样! 您可以使用任何您定义的可注射服务配置或子配置 !

// app.service.ts
import { Injectable } from '@nestjs/common';
import { RootConfig, DatabaseConfig, TableConfig } from './config';

@Injectable()
export class AppService {
  // inject any config or sub-config you like
  constructor(
    private config: RootConfig,
    private databaseConfig: DatabaseConfig,
    private tableConfig: TableConfig,
  ) {}

  // enjoy type safety!
  public show(): any {
    const out = [
      `root.name: ${this.config.name}`,
      `root.database.name: ${this.databaseConfig.name}`,
      `root.database.table.name: ${this.tableConfig.name}`,
    ].join('\n');

    return `${out}\n`;
  }
}

举个例子,请访问 代码框,或者我们的 实例 文件夹.

使用装载器

使用 dotenv 加载器

这个 dotenvLoader 函数允许您加载配置 多腾v,这类似于 正式配置模块。 您可以使用此加载器从 .env 文件或环境变量.

示例

TypedConfigModule.forRoot({
  schema: RootConfig,
  load: dotenvLoader({
    /* options */
  }),
});

通过选项

这个 dotenvLoader 函数可选择预期 a DotenvLoaderOptions 作为第一个参数的对象 :

export interface DotenvLoaderOptions {
  /**
   * If set, use the separator to parse environment variables to objects.
   *
   * @example
   *
   * ```bash
   * app__port=8080
   * db__host=127.0.0.1
   * db__port=3000
   * ```
   *
   * if `separator` is set to `__`, environment variables above will be parsed as:
   *
   * ```json
   * {
   *     "app": {
   *         "port": 8080
   *     },
   *     "db": {
   *         "host": "127.0.0.1",
   *         "port": 3000
   *     }
   * }
   * ```
   */
  separator?: string;

  /**
   * If set, this function will transform all environment variable keys prior to parsing.
   *
   * Be aware: If you transform multiple keys to the same value only one will remain!
   *
   * @example
   *
   * .env file: `PORT=8080` and `keyTransformer: key => key.toLowerCase()` results in `{"port": 8080}`
   *
   * @param key environment variable key
   */
  keyTransformer?: (key: string) => string;

  /**
   * If "true", environment files (`.env`) will be ignored.
   */
  ignoreEnvFile?: boolean;

  /**
   * If "true", predefined environment variables will not be validated.
   */
  ignoreEnvVars?: boolean;

  /**
   * Path to the environment file(s) to be loaded.
   */
  envFilePath?: string | string[];

  /**
   * A boolean value indicating the use of expanded variables.
   * If .env contains expanded variables, they'll only be parsed if
   * this property is set to true.
   *
   * Internally, dotenv-expand is used to expand variables.
   */
  expandVariables?: boolean;
}

使用文件加载器

这个 fileLoader 函数允许您加载配置 宇宙图您可以使用此加载器从带有各种扩展名的文件装入配置,例如 .json, (中文(简体) ), .yaml, (中文(简体) ), .toml 或者说 .js。 。 。 .

默认, fileLoader 搜索 .env.{ext} (ext = json, yaml, toml, js) 配置文件开始于 process.cwd(),并继续搜索目录树,直到它找到一些可接受的配置(或点击主目录). 此外,当前环境的配置优先于一般配置(.env.development.toml 正在装入而不是 .env.toml 何时 NODE_ENV=development(中文(简体) )

示例

TypedConfigModule.forRoot({
  schema: RootConfig,
  load: fileLoader({
    /* options */
  }),
});

通过选项

这个 fileLoader 函数可选择预期 a FileLoaderOptions 作为第一个参数的对象 :

import { OptionsSync } from 'cosmiconfig';

export interface FileLoaderOptions extends Partial<OptionsSync> {
  /**
   * basename of config file, defaults to `.env`.
   *
   * In other words, `.env.yaml`, `.env.yml`, `.env.json`, `.env.toml`, `.env.js`
   * will be searched by default.
   */
  basename?: string;
  /**
   * Use given file directly, instead of recursively searching in directory tree.
   */
  absolutePath?: string;
  /**
   * The directory to search from, defaults to `process.cwd()`. See: https://github.com/davidtheclark/cosmiconfig#explorersearch
   */
  searchFrom?: string;
  /**
   * If "true", ignore environment variable substitution.
   * Default: true
   */
  ignoreEnvironmentVariableSubstitution?: boolean;
}

如果您想要为其他扩展添加支持, 您可以使用 loaders 提供的财产 cosmiconfig数字 :

TypedConfigModule.forRoot({
  schema: RootConfig,
  load: fileLoader({
    // .env.ini has the highest priority now
    loaders: {
      '.ini': iniLoader,
    },
  }),
});

使用目录加载器

这个 directoryLoader 函数允许您在给定目录中装入配置.

文件的基名将解释为配置名空间,例如:

.
└─config
    ├── app.toml
    └── db.toml

// app.toml
foo = 1

// db.toml
bar = 1

上述文件夹将生成如下配置 :

{
  "app": {
    "foo": 1
  },
  "db": {
    "bar": 1
  }
}

示例

TypedConfigModule.forRoot({
  schema: RootConfig,
  load: directoryLoader({
    directory: '/absolute/path/to/config/directory',
    /* other cosmiconfig options */
  }),
});

通过选项

这个 directoryLoader 函数可选择预期 a DirectoryLoaderOptions 作为第一个参数的对象 :

import { OptionsSync } from 'cosmiconfig';

export interface DirectoryLoaderOptions extends OptionsSync {
  /**
   * The directory containing all configuration files.
   */
  directory: string;
  /**
   * File regex to include.
   */
  include?: RegExp;
  /**
   * If "true", ignore environment variable substitution.
   * Default: true
   */
  ignoreEnvironmentVariableSubstitution?: boolean;
  /**
   * If "true", disallow undefined environment variables.
   * Default: true
   */
  disallowUndefinedEnvironmentVariables?: boolean;
}

如果您想要为其他扩展添加支持, 您可以使用 loaders 提供的财产 cosmiconfig数字 :

TypedConfigModule.forRoot({
  schema: RootConfig,
  load: directoryLoader({
    directory: '/path/to/configuration',
    // .env.ini has the highest priority now
    loaders: {
      '.ini': iniLoader,
    },
  }),
});

使用远程加载器

这个 remoteLoader 函数允许您从远程端点加载配置,例如配置中心。 内部 @nestjs/ axios (英语) 用于执行 http 请求.

示例

// forRootAsync should be used when loading configuration asynchronously
TypedConfigModule.forRootAsync({
  schema: RootConfig,
  load: remoteLoader('http://localhost:8080', {
    /* options */
  }),
});

通过选项

这个 remoteLoader 函数可选择预期 a RemoteLoaderOptions 对象作为第二个参数,它接受所有 axios 请求配置除 url。 。 。 .

export interface RemoteLoaderOptions extends AxiosRequestConfigWithoutUrl {
  /**
   * Config file type
   */
  type?: ((response: any) => RemoteLoaderConfigType) | RemoteLoaderConfigType;

  /**
   * A function that maps http response body to corresponding config object
   */
  mapResponse?: (config: any) => Promise<any> | any;

  /**
   * A function that determines if the request should be retried
   */
  shouldRetry?: (response: AxiosResponse) => boolean;

  /**
   * Number of retries to perform, defaults to 3
   */
  retries?: number;

  /**
   * Interval in milliseconds between each retry
   */
  retryInterval?: number;
}

你可以用这个 mapResponse 功能在解析前预处理服务器响应 type,并使用 shouldRetry 函数来确定服务器响应是否有效。 当服务器响应无效时, 您可以使用 retries 财务报告和审定财务报表 retryInterval 调整重试策略。 例如:

/*
  Example server response:
  {
    "code": 0,
    "fileName": ".env.yaml",
    "fileType": "yaml",
    "fileContent": "database:\n    table:\n        name: example"
  }
*/

TypedConfigModule.forRootAsync({
    schema: RootConfig,
    load: remoteLoader('http://localhost:8080', {
        type: response => response.fileType,
        mapResponse: response => response.fileContent
        // retry when http status is not 200, or response code is not zero
        shouldRetry: response => response.data.code !== 0
        retries: 3,
        retryInterval: 3000
    }),
})

使用多加载器

从文件系统装入配置对于开发来说是方便的,但是在部署的时候,你可能需要从环境变量装入配置,特别是在被打乱的环境中. 这可以通过提供多台装载机实现. 例如:

TypedConfigModule.forRoot({
  schema: RootConfig,
  // Loaders having larger index take precedence over smaller ones,
  // make sure dotenvLoader comes after fileLoader ensures that
  // environment variables always have the highest priority
  load: [
    fileLoader({
      /* options */
    }),
    dotenvLoader({
      /* options */
    }),
  ],
});

使用自定义装入器

如果提供本地装载机 nest-typed-config 无法满足您的需要,您可以执行自定义加载器。 可以通过提供一个函数,通过该函数同步或同步返回配置对象 load 选项。 例如:

TypedConfigModule.forRootAsync({
  schema: RootConfig,
  load: async () => {
    return {
      host: '127.0.0.1',
      port: 3000,
    };
  },
});

可变替代品的使用

这个 ${PORT} 替换特性允许您使用环境变量 。 您也可以提供默认值,并在配置中引用另一个变量

如果您有类似下面的配置文件

database:
  host: 127.0.0.1
  port: ${PORT:-12345}
  url: ${database.host}:${database:port}

您为端口设置了环境变量

PORT=9000

设置在文件记录选项中忽略了环境可变替换为虚假

load: fileLoader({
  ignoreEnvironmentVariableSubstitution: false,
}),

接下来 fileloader 将决定 ${PORT} 占位符并替换为环境变量. 你会得到新的配置 像下一个

database:
  host: 127.0.0.1
  port: 9000
  url: 127.0.0.1:9000

如果您不会为端口设置环境变量, 那么您将会得到像下面一个这样的新配置

database:
  host: 127.0.0.1
  port: 12345
  url: 127.0.0.1:12345

[注] 当您使用可变量替代时,如果您使用默认变量或env变量,则数值可以是字符串,您需要将变压器应用到类字段,以获得数值的正确类型.

export class Config {
  @IsString()
  public readonly host!: string;

  @IsNumber()
  @Type(() => Number)
  public readonly port!: number;

  @IsString()
  public readonly url!: string;
}

默认值

在配置图中定义您的默认值, 您准备出发 :

// config.ts
export class Config {
  @IsString()
  public readonly host: string = '127.0.0.1';

  @IsNumber()
  public readonly port: number = 3000;
}

转换原始配置

环境变量总是被装入为字符串,但配置方案不是. 在这种情况下,你可以将原始配置转换为 normalize 函数 :

// config.ts
export class Config {
  @IsString()
  public readonly host: string;

  @IsNumber()
  public readonly port: number;
}

// app.module.ts
TypedConfigModule.forRoot({
  schema: RootConfig,
  load: dotenvLoader(),
  normalize(config) {
    config.port = parseInt(config.port, 10);
    return config;
  },
});

自定义获取器

您可以定义配置图上的自定义获取器以提取共同逻辑 :

export class Config {
  @IsString()
  public readonly host: string = '127.0.0.1';

  @IsNumber()
  public readonly port: number = 3000;

  @IsString()
  public get url(): string {
    return `http://${this.host}:${this.port}`;
  }
}

多个外观

打电话 TypedConfigModule.forRoot 多次,你准备走了!

PS:请不要在计划之间共享任何类或子类,否则Nest.js不会知道要注射哪个类.

// config.ts
export class FooConfig {
  @IsString()
  foo!: string;
}
export class BazConfig {
  @IsString()
  baz!: string;
}

// app.module.ts
@Module({
  imports: [
    // load FooConfig from config file
    TypedConfigModule.forRoot({
      schema: FooConfig,
      load: fileLoader(),
    }),
    // load BazConfig from environment variables
    TypedConfigModule.forRoot({
      schema: BazConfig,
      load: dotenvLoader(),
    }),
  ],
})
export class AppModule {}

自定义验证函数

如果默认 validate 函数不设置您的使用大小写, 您可以像下面的例子那样提供 :

TypedConfigModule.forRoot({
  schema: RootConfig,
  validate: (rawConfig: any) => {
    const config = plainToClass(RootConfig, rawConfig);
    const schemaErrors = validateSync(config, {
      forbidUnknownValues: true,
      whitelist: true,
    });

    if (schemaErrors.length) {
      throw new Error(TypedConfigModule.getConfigErrorMessage(schemaErrors));
    }

    return config as RootConfig;
  },
});

使用 Nest 的 IoC 容器外的配置( 装饰器中的用户)

小心点!

使用 Nest 的 IoC 容器外的配置将:

  1. 让你更努力的写作测试.
  2. 强制您注册 TypedConfigModule 同步使用 forRoot因为在这种情况下同步的配置加载是没有道理的.

怎么样

由于JavaScript加载模块的性质,装饰器在Nest模块初始化之前被执行. 如果你想在装饰器中获得配置值 @Controller() 或者说 @WebSocketGateway(),配置模块应在应用程序拖放前初始化.

假设我们需要从配置中注入路由信息,那么我们可以这样定义配置:

// config.ts
import { Type } from 'class-transformer';
import { ValidateNested, IsString } from 'class-validator';

export class RouteConfig {
  @IsString()
  public readonly app!: string;
}

export class RootConfig {
  @ValidateNested()
  @Type(() => RouteConfig)
  public readonly route!: RouteConfig;
}

然后创建配置文件 :

route:
  app: /app

创建配置文件后, 我们可以初始化 ConfigModule 与 TypedConfigModule选择 RootConfig 从 ConfigModule 使用 selectConfig 方法.

// config.module.ts
import { TypedConfigModule, fileLoader, selectConfig } from 'nest-typed-config';
import { RouteConfig } from './config';

export const ConfigModule = TypedConfigModule.forRoot({
  schema: RootConfig,
  load: fileLoader(),
});

export const rootConfig = selectConfig(ConfigModule, RootConfig);
export const routeConfig = selectConfig(ConfigModule, RouteConfig);

就这样! 你用得着 rootConfig 财务报告和审定财务报表 routeConfig 现在在你的应用程序里!

如果目标配置模型被标记 @Optional(),你应该打电话 selectConfig 与 { allowOptional: true } 允许可选配置.

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { rootConfig } from './config.module';

@Controller(routeConfig.app)
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  show(): void {
    return this.appService.show();
  }
}

举个例子,请访问 代码框,或者我们的 实例 文件夹.

API 密码

请参看我们 API 网站 用于完整文档.

更改日志

请参考 变化日志.md

许可证

麻省理工学院。 。 。 .

恒星历史

Star History Chart

版本与发布记录

@coast/nest-typed-config 共发布 5 个版本,首次发布于 2025/05/20;过去 12 个月发布了 1 个版本。

版本发布日期距今
4.0.0latest2026/10/2813 天前
3.0.22025/05/221.5 年前
3.0.12025/05/221.5 年前
3.0.02025/05/211.5 年前
2.9.42025/05/201.5 年前

关于 @coast/nest-typed-config 的常见问题

@coast/nest-typed-config 是什么?

Nest 框架的直观、类型安全配置模块

如何安装 @coast/nest-typed-config?

在项目目录运行 npm install @coast/nest-typed-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:rxjs(^7.1.0)、@nestjs/common(^11.0.0 || ^12.0.0)、class-validator(*)、reflect-metadata(>= 0.1.12 < 0.3)、class-transformer(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@coast/nest-typed-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@coast/nest-typed-config 可以商用吗?

@coast/nest-typed-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@coast/nest-typed-config 的下载量有多少?

根据 npm 官方下载统计,@coast/nest-typed-config 在 2026/10/10 – 2026/11/08 这 30 天内被下载 8,960 次,日均约 299 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@coast/nest-typed-config 还在维护吗?

最新版本 4.0.0 发布于 2026/10/28(13 天前);至今共发布 5 个版本,其中过去 12 个月发布了 1 个;首次发布于 2025/05/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。