TypeScript में एरर हैंडलिंग: बेसिक try/catch से प्रोडक्शन पैटर्न तक
\n\nएरर हैंडलिंग सिर्फ try/catch ब्लॉक्स तक सीमित नहीं है। TypeScript में, सख्त टाइप सिस्टम की बदौलत, हम एरर मैनेजमेंट को एक नए स्तर पर ले जा सकते हैं। इस लेख में, हम उन्नत तकनीकों पर चर्चा करेंगे जो आपको अधिक विश्वसनीय और अनुमानित कोड लिखने में मदद करेंगी।
TypeScript में स्टैंडर्ड try/catch की समस्या
\n\nक्लासिक try/catch ब्लॉक में TypeScript की एक बुनियादी समस्या है: कैच की गई एरर का टाइप unknown (या पुराने वर्जन में any) होता है। इसका मतलब है कि TypeScript को यह नहीं पता होता कि हम किस ऑब्जेक्ट के साथ काम कर रहे हैं।
try {\n // कोई खतरनाक कोड\n const result = JSON.parse('{"data": 123}');\n} catch (error) {\n // error का टाइप unknown है\n // सीधे error.message कॉल नहीं कर सकते\n console.log(error.message); // कम्पाइलेशन एरर!\n}\n\nयह डेवलपर्स को या तो टाइप्स को इग्नोर करने या बड़ी-बड़ी चेक्स लिखने पर मजबूर करता है। आइए देखें कि इस समस्या को उन्नत स्तर पर कैसे हल किया जाए।
\n\n1. टाइपिंग के साथ कस्टम एरर सिस्टम बनाना
\n\nसामान्य Error फेंकने के बजाय, कस्टम एरर का एक पदानुक्रम बनाएं। इससे TypeScript कम्पाइल टाइम पर ही एरर टाइप्स को अलग-अलग पहचान सकेगा।
// सभी एप्लिकेशन एरर के लिए बेस क्लास\nclass AppError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode: number = 500\n ) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n// विशिष्ट एरर टाइप्स\nclass ValidationError extends AppError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n }\n}\n\nclass NotFoundError extends AppError {\n constructor(resource: string) {\n super(`${resource} नहीं मिला`, 'NOT_FOUND', 404);\n }\n}\n\nclass DatabaseError extends AppError {\n constructor(message: string) {\n super(message, 'DB_ERROR', 500);\n }\n}\n\n// उपयोग\nfunction findUser(id: string): User {\n if (!id) throw new ValidationError('ID अनिवार्य है');\n // ... खोज लॉजिक\n if (!user) throw new NotFoundError('उपयोगकर्ता');\n return user;\n}\n\n2. एरर हैंडलिंग के लिए Type Guards
\n\nविभिन्न एरर टाइप्स को सुरक्षित रूप से हैंडल करने के लिए type guards का उपयोग करें। catch में unknown के साथ काम करने के लिए यह एक मुख्य पैटर्न है।
// AppError के लिए Type guard\nfunction isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n// ValidationError के लिए Type guard\nfunction isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError;\n}\n\n// उन्नत हैंडलिंग\ntry {\n const user = findUser(userId);\n} catch (error) {\n if (isValidationError(error)) {\n // TypeScript जानता है कि error — ValidationError है\n console.error(`वैलिडेशन एरर: ${error.message}`);\n return { status: 400, message: error.message };\n }\n \n if (isAppError(error)) {\n // error — AppError है\n console.error(`एरर कोड: ${error.code}`);\n return { status: error.statusCode, message: error.message };\n }\n \n // अज्ञात एरर\n if (error instanceof Error) {\n console.error('अज्ञात एरर:', error.message);\n }\n \n return { status: 500, message: 'सर्वर की आंतरिक त्रुटि' };\n}\n\n3. Result-पैटर्न (Either monad)
\n\nयह एक्सेप्शन का एक विकल्प है जो एरर हैंडलिंग को टाइप स्तर पर स्पष्ट बनाता है। एरर फेंकने के बजाय, फंक्शन एक ऑब्जेक्ट लौटाता है जिसमें या तो सफल परिणाम या एरर हो सकता है।
\n\n// Result-पैटर्न के लिए टाइप डेफिनिशन\ntype Success<T> = { success: true; data: T };\ntype Failure<E> = { success: false; error: E };\ntype Result<T, E> = Success<T> | Failure<E>;\n\n// सहायक फंक्शन\nfunction success<T>(data: