slogan3

Typescript Error Handling met Custom Exceptions en Logging

description

Met deze prompt leer ik hoe ik mijn foutafhandeling in Typescript kan verbeteren door custom exceptions te gebruiken, waardoor ik fouten beter kan onderscheiden en afhandelen. Het helpt bij het opzetten van een gestructureerd foutloggingsysteem, wat de diagnose en onderhoudbaarheid van mijn code aanzienlijk verbetert. Dit is effectiever dan standaard foutafhandeling, die vaak te algemeen is en minder inzicht biedt.

prompt

Leg uit hoe ik in Typescript aangepaste foutklassen kan maken en gebruiken om specifieke fouten in mijn applicatie te onderscheiden voor <beschrijving van de foutscenario' ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
In TypeScript kun je aangepaste foutklassen maken door een klasse te definiëren die de ingebouwde `Error`-klasse uitbreidt. Hiermee kun je specifieke fouten onderscheiden en gerichte afhandeling mogelijk maken, bijvoorbeeld bij invoervalidatie in een gebruikersregistratieproces. **Stap 1: Definieer aangepaste foutklassen** ```typescript class InvalidEmailError extends Error { constructor(message: string = "Ongeldig e-mailadres") { super(message); this.name = "InvalidEmailError"; Object.setPrototypeOf(this, new.target.prototype); // voor juiste prototype-keten } } class PasswordTooWeakError extends Error { constructor(message: string = "Wachtwoord is te zwak") { super(message); this.name = "PasswordTooWeakError"; Object.setPrototypeOf(this, new.target.prototype); } } ``` **Stap 2: Gebruik van de foutklassen bij validatie** ```typescript function validateEmail(email: string): void { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { throw new InvalidEmailError(); } } function validatePassword(password: string): void { if (password.length < 8) { throw new PasswordTooWeakError("Wachtwoord moet minimaal 8 tekens bevatten"); } // andere checks kunnen hier toegevoegd worden } ``` **Stap 3: Fouten werpen en afhandelen** ```typescript function registreerGebruiker(email: string, wachtwoord: string): void { try { validateEmail(email); validatePassword(wachtwoord); // verdere registratie-logica console.log("Gebruiker succesvol geregistreerd"); } catch (error) { if (error instanceof InvalidEmailError) { console.error(`Invoerfout: ${error.message}`); } else if (error instanceof PasswordTooWeakError) { console.error(`Invoerfout: ${error.message}`); } else { console.error("Onbekende fout:", error); } // eventueel loggen naar een extern systeem } } ``` **Stap 4: Loggingsysteem optimaliseren** Gebruik bij voorkeur een logging-bibliotheek zoals `winston` of `pino` voor een gestructureerde logging: ```typescript import * as winston from 'winston'; const logger = winston.createLogger({ level: 'error', format: winston.format.json(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'fouten.log' }) ], }); // In de catch-block: logger.error(`Fout bij registratie: ${error.name} - ${error.message}`); ``` **Samenvatting:** - Maak custom foutklassen door `Error` uit te breiden. - Gooi deze fouten bij specifieke validatieproblemen. - Vang ze af in je applicatielogica en handel per fouttype af. - Gebruik een gestructureerd logging-systeem voor overzicht en troubleshooting. Zo houd je je code overzichtelijk, kun je gerichte feedback geven aan gebruikers en fouten effectief monitoren.
provider: deepseek
model: deepseek-chat
Zeker, hier is een uitgebreide uitleg over het maken en gebruiken van aangepaste foutklassen in TypeScript voor invoervalidatie. --- ### 1. Aangepaste Foutklassen Definieren ```typescript // Basis aangepaste foutklasse abstract class CustomError extends Error { abstract statusCode: number; constructor(message: string) { super(message); this.name = this.constructor.name; Error.captureStackTrace(this, this.constructor); } abstract serializeErrors(): { message: string; field?: string }[]; } // Specifieke validatiefouten class ValidationError extends CustomError { statusCode = 400; constructor(public message: string, public field?: string) { super(message); } serializeErrors() { return [{ message: this.message, field: this.field }]; } } class EmailAlreadyExistsError extends CustomError { statusCode = 409; constructor() { super('E-mailadres is al in gebruik'); } serializeErrors() { return [{ message: this.message }]; } } class PasswordStrengthError extends CustomError { statusCode = 400; constructor() { super('Wachtwoord voldoet niet aan de vereisten'); } serializeErrors() { return [{ message: this.message }]; } } ``` ### 2. Validatiefuncties met Foutafhandeling ```typescript class UserValidator { static validateEmail(email: string): void { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!email) { throw new ValidationError('E-mail is verplicht', 'email'); } if (!emailRegex.test(email)) { throw new ValidationError('Ongeldig e-mailformaat', 'email'); } } static validatePassword(password: string): void { if (!password) { throw new ValidationError('Wachtwoord is verplicht', 'password'); } if (password.length < 8) { throw new ValidationError('Wachtwoord moet minimaal 8 tekens bevatten', 'password'); } if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(password)) { throw new PasswordStrengthError(); } } static validateUsername(username: string): void { if (!username) { throw new ValidationError('Gebruikersnaam is verplicht', 'username'); } if (username.length < 3) { throw new ValidationError('Gebruikersnaam moet minimaal 3 tekens bevatten', 'username'); } } } ``` ### 3. Gebruikersregistratie Service ```typescript class UserService { private existingEmails = new Set<string>(); async registerUser(userData: { email: string; password: string; username: string; }): Promise<void> { try { // Valideer invoer UserValidator.validateEmail(userData.email); UserValidator.validatePassword(userData.password); UserValidator.validateUsername(userData.username); // Controleer of e-mail al bestaat if (this.existingEmails.has(userData.email)) { throw new EmailAlreadyExistsError(); } // Registratie logica hier... this.existingEmails.add(userData.email); console.log('Gebruiker succesvol geregistreerd'); } catch (error) { if (error instanceof CustomError) { throw error; // Gooi door naar error handler } throw new ValidationError('Onverwachte validatiefout'); } } } ``` ### 4. Error Handling Middleware (Express.js) ```typescript import { Request, Response, NextFunction } from 'express'; interface ErrorResponse { errors: { message: string; field?: string }[]; } export const errorHandler = ( error: Error, req: Request, res: Response, next: NextFunction ): void => { // Log de error logger.error('Fout opgetreden:', { error: error.message, stack: error.stack, timestamp: new Date().toISOString(), path: req.path, method: req.method }); // Custom error handling if (error instanceof CustomError) { res.status(error.statusCode).json({ errors: error.serializeErrors() } as ErrorResponse); return; } // Onverwachte errors res.status(500).json({ errors: [{ message: 'Er is een onverwachte fout opgetreden' }] } as ErrorResponse); }; ``` ### 5. Logger Implementatie ```typescript class Logger { static error(message: string, metadata?: any): void { const logEntry = { level: 'ERROR', timestamp: new Date().toISOString(), message, metadata }; console.error(JSON.stringify(logEntry)); // Hier kun je ook naar een file of external service loggen } static info(message: string, metadata?: any): void { const logEntry = { level: 'INFO', timestamp: new Date().toISOString(), message, metadata }; console.log(JSON.stringify(logEntry)); } } ``` ### 6. Gebruik in een Express Route ```typescript import express from 'express'; const app = express(); app.use(express.json()); app.post('/register', async (req: Request, res: Response, next: NextFunction) => { try { const userService = new UserService(); await userService.registerUser(req.body); res.status(201).json({ message: 'Registratie succesvol' }); } catch (error) { next(error); // Door naar error handler } }); // Error handler middleware toevoegen app.use(errorHandler); ``` ### 7. Gebruiksvoorbeeld en Response **Request:** ```json { "email": "ongeldig-email", "password": "zwak", "username": "" } ``` **Response (400 Bad Request):** ```json { "errors": [ { "message": "Ongeldig e-mailformaat", "field": "email" }, { "message": "Wachtwoord moet minimaal 8 tekens bevatten", "field": "password" }, { "message": "Gebruikersnaam is verplicht", "field": "username" } ] } ``` ### Belangrijke Voordelen: 1. **Type Safety**: Volledige TypeScript ondersteuning 2. **Gestructureerde errors**: Duidelijke error messages met veld informatie 3. **Logging**: Gedetailleerde error logging voor debugging 4. **Consistente API**: Uniform error response format 5. **Uitbreidbaar**: Eenvoudig nieuwe error types toevoegen Dit patroon zorgt voor robuuste foutafhandeling en duidelijke feedback naar gebruikers terwijl developers gedetailleerde logging hebben voor debugging.