slogan3

Help me implementeren van een type-veilige configuratiebeheeroplossing in TypeScript voor {{config_type}}.

description

Door het implementeren van een type-veilige configuratiebeheeroplossing, verbeter je de betrouwbaarheid van je toepassing, verminder je runtime-fouten, en zorg je dat je configuraties correct getypeerd en gevalideerd worden, wat leidt tot soepelere ontwikkeling en onderhoudsprocessen.

prompt

try_prompt

Geef begeleiding over hoe je een robuust configuratiebeheersysteem in TypeScript kunt maken dat typeveiligheid garandeert voor {{config_type}}. Inclusief voorbeelden va ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Het opzetten van een robuust configuratiebeheersysteem in TypeScript dat typeveiligheid garandeert voor omgevingsvariabelen vereist enkele stappen: het definiëren van types, het laden van configuraties uit verschillende bronnen, en runtime validatie. Hier is een gestructureerde aanpak met voorbeelden: 1. Definieer je configuratietypes Maak een duidelijk en strikt type voor je configuratie. Bijvoorbeeld: ```typescript // types.ts export interface Config { PORT: number; DATABASE_URL: string; ENABLE_FEATURE_X: boolean; LOG_LEVEL: 'debug' | 'info' | 'warn' | 'error'; } ``` 2. Laad en parse omgevingsvariabelen Gebruik `process.env` en converteer de waarden naar de juiste types. Dit doe je meestal met helper functies: ```typescript // loadConfig.ts import { Config } from './types'; function parseNumber(value: string | undefined, defaultValue?: number): number { const parsed = Number(value); if (isNaN(parsed)) { if (defaultValue !== undefined) return defaultValue; throw new Error(`Kan "${value}" niet parseren naar een nummer.`); } return parsed; } function parseBoolean(value: string | undefined): boolean { return value === 'true'; } function parseLogLevel(value: string | undefined): 'debug' | 'info' | 'warn' | 'error' { const levels = ['debug', 'info', 'warn', 'error'] as const; if (value && levels.includes(value)) { return value as typeof levels[number]; } return 'info'; // of throw een error } export function loadConfig(): Config { return { PORT: parseNumber(process.env.PORT), DATABASE_URL: process.env.DATABASE_URL || '', ENABLE_FEATURE_X: parseBoolean(process.env.ENABLE_FEATURE_X), LOG_LEVEL: parseLogLevel(process.env.LOG_LEVEL), }; } ``` 3. Validatie en typeveiligheid Gebruik bijvoorbeeld `zod` of `io-ts` voor runtime validatie, zodat je zeker bent dat de configuratie correct is: ```typescript // validateConfig.ts import { z } from 'zod'; const ConfigSchema = z.object({ PORT: z.number(), DATABASE_URL: z.string().nonempty(), ENABLE_FEATURE_X: z.boolean(), LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']), }); export function validateConfig(config: any) { return ConfigSchema.parse(config); } ``` 4. Integratie en gebruik Combineer alles in je hoofdapplicatie: ```typescript // main.ts import { loadConfig } from './loadConfig'; import { validateConfig } from './validateConfig'; const rawConfig = loadConfig(); try { const config = validateConfig(rawConfig); // gebruik config veilig } catch (e) { console.error('Configuratiefout:', e); process.exit(1); } ``` **Samenvatting:** - Definieer expliciete types voor je configuratie. - Laad omgevingsvariabelen en converteer ze op type-niveau. - Gebruik een runtime validatietool zoals `zod` om de configuratie te controleren. - Zorg dat fouten tijdens de startup worden afgehandeld, zodat je niet met ongeldige configuratie draait. Met deze aanpak garandeer je dat je configuraties typeveilig en correct gevalideerd zijn, zowel compileer- als runtime.
provider: deepseek
model: deepseek-chat
Hier is een uitgebreide gids voor het creëren van een robuust configuratiebeheersysteem in TypeScript: ## 1. Basis Configuratie Type Definitie ```typescript // types/config.ts interface DatabaseConfig { host: string; port: number; username: string; password: string; database: string; } interface ApiConfig { baseUrl: string; timeout: number; apiKey: string; } interface AppConfig { environment: 'development' | 'staging' | 'production'; port: number; database: DatabaseConfig; api: ApiConfig; logLevel: 'error' | 'warn' | 'info' | 'debug'; } ``` ## 2. Schema Validatie met Zod ```typescript // validation/configSchema.ts import { z } from 'zod'; const DatabaseSchema = z.object({ host: z.string().min(1, "Database host is verplicht"), port: z.number().int().min(1).max(65535), username: z.string().min(1), password: z.string().min(1), database: z.string().min(1) }); const ApiSchema = z.object({ baseUrl: z.string().url(), timeout: z.number().int().positive(), apiKey: z.string().min(1) }); const AppConfigSchema = z.object({ environment: z.enum(['development', 'staging', 'production']), port: z.number().int().min(1).max(65535), database: DatabaseSchema, api: ApiSchema, logLevel: z.enum(['error', 'warn', 'info', 'debug']) }); ``` ## 3. Configuratie Loader met Type Safety ```typescript // config/ConfigLoader.ts import { z } from 'zod'; import { AppConfigSchema } from '../validation/configSchema'; import type { AppConfig } from '../types/config'; class ConfigLoader { private config: AppConfig | null = null; async load(): Promise<AppConfig> { if (this.config) { return this.config; } // Laad configuratie uit verschillende bronnen const rawConfig = await this.loadFromMultipleSources(); // Valideer de configuratie const validatedConfig = this.validateConfig(rawConfig); this.config = validatedConfig; return validatedConfig; } private async loadFromMultipleSources(): Promise<unknown> { // 1. Environment variabelen const envConfig = this.loadFromEnv(); // 2. Configuratiebestanden (optioneel) const fileConfig = await this.loadFromFile(); // 3. Default waarden const defaultConfig = this.getDefaultConfig(); return { ...defaultConfig, ...fileConfig, ...envConfig }; } private loadFromEnv(): Partial<AppConfig> { return { environment: process.env.NODE_ENV as AppConfig['environment'], port: process.env.PORT ? parseInt(process.env.PORT) : undefined, database: { host: process.env.DB_HOST, port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : undefined, username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_NAME }, api: { baseUrl: process.env.API_BASE_URL, timeout: process.env.API_TIMEOUT ? parseInt(process.env.API_TIMEOUT) : undefined, apiKey: process.env.API_KEY }, logLevel: process.env.LOG_LEVEL as AppConfig['logLevel'] }; } private async loadFromFile(): Promise<Partial<AppConfig>> { try { // Voor development: laad uit config file if (process.env.NODE_ENV === 'development') { const config = await import('../../config/development.json'); return config.default || config; } } catch (error) { // Negeer als config file niet bestaat } return {}; } private getDefaultConfig(): Partial<AppConfig> { return { port: 3000, logLevel: 'info', api: { timeout: 5000 } }; } private validateConfig(rawConfig: unknown): AppConfig { try { return AppConfigSchema.parse(rawConfig) as AppConfig; } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.errors.map(err => `${err.path.join('.')}: ${err.message}` ).join('\n'); throw new Error(`Configuratie validatie mislukt:\n${errorMessages}`); } throw error; } } getConfig(): AppConfig { if (!this.config) { throw new Error('Configuratie niet geladen. Roep load() aan eerst.'); } return this.config; } } export const configLoader = new ConfigLoader(); ``` ## 4. Gebruik in de Applicatie ```typescript // app.ts import { configLoader } from './config/ConfigLoader'; async function bootstrap() { try { // Laad en valideer configuratie bij opstarten const config = await configLoader.load(); console.log('Configuratie succesvol geladen:'); console.log(`Environment: ${config.environment}`); console.log(`Database: ${config.database.host}:${config.database.port}`); // Start je applicatie met de gevalideerde configuratie startApplication(config); } catch (error) { console.error('Fout bij laden configuratie:', error.message); process.exit(1); } } function startApplication(config: AppConfig) { // Je applicatie logica hier console.log(`Applicatie gestart op poort ${config.port}`); } bootstrap(); ``` ## 5. Geavanceerde Features ### Environment-specifieke configuratie: ```typescript // config/EnvironmentConfig.ts import { z } from 'zod'; const EnvironmentSchema = z.object({ NODE_ENV: z.enum(['development', 'staging', 'production']), PORT: z.string().transform(val => parseInt(val, 10)), DB_HOST: z.string(), DB_PORT: z.string().transform(val => parseInt(val, 10)), DB_USERNAME: z.string(), DB_PASSWORD: z.string(), DB_NAME: z.string(), API_BASE_URL: z.string().url(), API_TIMEOUT: z.string().transform(val => parseInt(val, 10)), API_KEY: z.string(), LOG_LEVEL: z.enum(['error', 'warn', 'info', 'debug']) }); export class EnvironmentConfig { static validate() { return EnvironmentSchema.parse(process.env); } } ``` ### Configuratie met transformaties: ```typescript // config/AdvancedConfigLoader.ts import { z } from 'zod'; const AdvancedAppConfigSchema = AppConfigSchema.extend({ database: DatabaseSchema.extend({ // Transformeer host naar lowercase host: z.string().transform(host => host.toLowerCase()), // Valideer database naam database: z.string().regex(/^[a-zA-Z0-9_]+$/, "Ongeldige database naam") }), api: ApiSchema.extend({ // Zorg ervoor dat baseUrl eindigt met / baseUrl: z.string().transform(url => url.endsWith('/') ? url : `${url}/` ) }) }); ``` ## 6. Testen ```typescript // tests/ConfigLoader.test.ts import { configLoader } from '../config/ConfigLoader'; describe('ConfigLoader', () => { beforeEach(() => { // Reset process.env voor elke test delete process.env.NODE_ENV; delete process.env.DB_HOST; // ... reset andere env vars }); it('should load valid configuration', async () => { process.env.NODE_ENV = 'development'; process.env.DB_HOST = 'localhost'; process.env.DB_PORT = '5432'; process.env.DB_USERNAME = 'user'; process.env.DB_PASSWORD = 'pass'; process.env.DB_NAME = 'mydb'; process.env.API_BASE_URL = 'https://api.example.com'; process.env.API_TIMEOUT = '5000'; process.env.API_KEY = 'test-key'; process.env.LOG_LEVEL = 'info'; const config = await configLoader.load(); expect(config.database.host).toBe('localhost'); expect(config.environment).toBe('development'); }); it('should throw error for invalid configuration', async () => { process.env.NODE_ENV = 'invalid'; // Ongeldige waarde await expect(configLoader.load()).rejects.toThrow(); }); }); ``` ## Belangrijke Voordelen: 1. **Type Safety**: Volledige TypeScript ondersteuning 2. **Runtime Validatie**: Zod zorgt voor validatie tijdens runtime 3. **Flexibele Bronnen**: Ondersteunt multiple configuratiebronnen 4. **Vroegtijdige Foutdetectie**: Configuratiefouten worden direct gedetecteerd 5. **Documentatie**: Schema's dienen als documentatie 6. **Testbaar**: Eenvoudig te testen met verschillende configuraties Dit systeem garandeert dat je applicatie altijd start met een geldige configuratie en voorkomt runtime fouten door ontbrekende of ongeldige configuratiewaarden.