| title | Define a Type-Safe Configuration Schema | ||||
|---|---|---|---|---|---|
| id | define-config-schema | ||||
| skillLevel | intermediate | ||||
| applicationPatternId | core-concepts | ||||
| summary | Use Effect.Config primitives to define a schema for your application's configuration, ensuring type-safety and separation from code. | ||||
| tags |
|
||||
| rule |
|
||||
| related |
|
||||
| author | Sandro Maglione | ||||
| lessonOrder | 4 |
Define all external configuration values your application needs using the schema-building functions from Effect.Config, such as Config.string and Config.number.
This creates a single, type-safe source of truth for your configuration, eliminating runtime errors from missing or malformed environment variables and making the required configuration explicit.
import { Config, Effect, ConfigProvider, Layer } from "effect";
const ServerConfig = Config.nested("SERVER")(
Config.all({
host: Config.string("HOST"),
port: Config.number("PORT"),
})
);
// Example program that uses the config
const program = Effect.gen(function* () {
const config = yield* ServerConfig;
yield* Effect.logInfo(`Server config loaded: ${JSON.stringify(config)}`);
});
// Create a config provider with test values
const TestConfig = ConfigProvider.fromMap(
new Map([
["SERVER.HOST", "localhost"],
["SERVER.PORT", "3000"],
])
);
// Run with test config
Effect.runPromise(Effect.provide(program, Layer.setConfigProvider(TestConfig)));Explanation:
This schema ensures that both host and port are present and properly typed, and that their source is clearly defined.
Directly accessing process.env. This is not type-safe, scatters configuration access throughout your codebase, and can lead to parsing errors or undefined values.