Nest Typed Config
Nest-Typed-Config is a robust and intuitive configuration module designed for the NestJS framework, providing a type-safe approach to managing application settings. Unlike other configuration solutions like the official `@nestjs/config` or `nestjs-config`, this library eliminates the need for manual type-casting by allowing developers to define their configuration schema using TypeScript classes and decorators, similar to DTOs. It supports various loaders including environment variables, JSON, YAML, TOML, and remote endpoints, and integrates seamlessly with `class-validator` and `class-transformer` for comprehensive configuration validation and transformation. The current stable version is `2.10.1`, with active development and frequent releases to support new NestJS versions and introduce features like environment variable overrides and default values for file loaders.
Common errors
-
Error: Nest can't resolve dependencies of the TypedConfigModule (?). Please make sure that the argument ConfigSchema at index [0] is available in the TypedConfigModule context.
cause The `schema` property provided to `TypedConfigModule.forRoot` is either incorrect, undefined, or not a valid TypeScript class decorated for validation and transformation.fixEnsure the `schema` property points to a correctly imported TypeScript class, which should be decorated with `class-validator` and `class-transformer` decorators, and that `TypedConfigModule` can access it. -
Validation failed! Invalid value for "database.table.name".
cause Configuration values loaded from your files or environment variables do not conform to the validation rules defined in your schema class (e.g., a string was expected, but a number or incorrect type was provided).fixReview your configuration file (e.g., `.env.yaml`, `config.json`) and environment variables. Compare them against the type definitions and validation decorators (e.g., `@IsString()`, `@IsNumber()`, `@ValidateNested()`) in your `RootConfig` and nested classes. -
TypeError: TypedConfigModule.forRoot is not a function
cause This error typically indicates that `nest-typed-config` is being imported using CommonJS `require()` syntax in a project that is primarily configured for ES modules, or vice-versa, leading to incorrect module resolution.fixEnsure you are using ES module `import { TypedConfigModule } from 'nest-typed-config';` syntax. If your project uses CommonJS, you might need to adjust your TypeScript configuration or build process to correctly handle module interop, or ensure `type: "module"` is set in your `package.json` for ESM projects. -
Error: Could not load configuration files or environment variables. No loaders returned a valid configuration.
cause No configured loader (e.g., `fileLoader`, `dotenvLoader`) found or successfully parsed any configuration data, or validation failed silently if `validate` is set to `false`.fixVerify that your configuration files exist at the specified `absolutePath` and that their format (e.g., YAML, JSON) is correct. Check loader options (e.g., `yaml: true`, `json: true`) and ensure environment variables are correctly set if using `dotenvLoader`.
Warnings
- breaking Versions prior to `2.9.4` may not be compatible with NestJS v11, requiring updates to peer dependencies and core NestJS types. Using an older version with NestJS v11 can lead to type errors or runtime issues.
- gotcha Older versions of `nest-typed-config` had a stricter peer dependency requirement for `reflect-metadata` (specifically `0.1.x`), causing installation conflicts with newer NestJS projects that often utilize `0.2.x`.
- gotcha By default, `nest-typed-config` installs all optional dependencies required for various loaders (JSON, YAML, TOML, remote). This can significantly increase the total bundle size and installation time, especially if only a few loaders are used.
- gotcha Versions prior to `2.10.1` might encounter issues when bundling NestJS applications with Webpack, particularly concerning how file loaders resolve paths, leading to build failures or incorrect configuration loading.
- gotcha Advanced features like setting default values for file loaders and variable substitution using `dotenv-expand` syntax were introduced incrementally. These features are not available in older versions, limiting configuration flexibility.
Install
-
npm install nest-typed-config -
yarn add nest-typed-config -
pnpm add nest-typed-config
Imports
- TypedConfigModule
const { TypedConfigModule } = require('nest-typed-config')import { TypedConfigModule } from 'nest-typed-config' - ConfigService
import { ConfigService } from '@nestjs/config'import { ConfigService } from 'nest-typed-config' - fileLoader
import fileLoader from 'nest-typed-config/dist/fileLoader'
import { fileLoader } from 'nest-typed-config'
Quickstart
import { Allow, ValidateNested, IsString, IsNumber } from 'class-validator';
import { Type } from 'class-transformer';
import { Module, Injectable } from '@nestjs/common';
import { TypedConfigModule, fileLoader } from 'nest-typed-config';
// config.ts
export class TableConfig {
@IsString()
public readonly name!: string;
}
export class DatabaseConfig {
@Type(() => TableConfig)
@ValidateNested()
public readonly table!: TableConfig;
}
export class RootConfig {
@Type(() => DatabaseConfig)
@ValidateNested()
public readonly database!: DatabaseConfig;
@IsString()
public readonly appHost!: string;
@IsNumber()
public readonly appPort!: number;
}
// app.module.ts (assuming a config.yaml or .env.yaml exists in the root)
// Example config.yaml:
// database:
// table:
// name: myapp_main
// appHost: localhost
// appPort: 3000
@Module({
imports: [
TypedConfigModule.forRoot({
schema: RootConfig,
load: fileLoader({
yaml: true,
absolutePath: process.cwd(),
ignoreEnvFile: false,
}),
isDevelopment: process.env.NODE_ENV !== 'production',
validate: true,
}),
],
})
export class AppModule {}
// app.service.ts
@Injectable()
export class AppService {
constructor(private readonly config: RootConfig) {}
getAppInfo(): string {
return `Application running at http://${this.config.appHost}:${this.config.appPort} with table: ${this.config.database.table.name}`;
}
}