معالجة الأخطاء في TypeScript: تقنيات متقدمة لـ try/catch

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

معالجة الأخطاء المتقدمة في TypeScript: من try/catch إلى حلول آمنة من حيث النوع



معالجة الأخطاء هي جانب بالغ الأهمية في التطوير باستخدام TypeScript. غالبًا ما يكون try/catch الأساسي غير كافٍ للتطبيقات المعقدة. في هذه المقالة، سنستعرض تقنيات متقدمة تساعد في جعل الكود أكثر موثوقية وقابلية للتنبؤ وأمانًا من حيث النوع.



1. مشكلة try/catch القياسي: فقدان الأنواع



العيب الرئيسي لـ catch التقليدي هو أن متغير الخطأ له نوع unknown (أو any في الإصدارات القديمة). وهذا يجبر المطور على التحقق من النوع يدويًا:



try {  riskyOperation();} catch (error) {  // error: unknown  if (error instanceof Error) {    console.error(error.message);  } else {    console.error('خطأ غير معروف', error);  }}


الحل: إنشاء أداة مساعدة لالتقاط الأخطاء بنوع محدد:



function getErrorMessage(error: unknown): string {  if (error instanceof Error) return error.message;  if (typeof error === 'string') return error;  if (error && typeof error === 'object' && 'message' in error) {    return String((error as { message: unknown }).message);  }  return 'حدث خطأ غير معروف';}

try { riskyOperation();} catch (error) { console.error(getErrorMessage(error));}


2. فئات الأخطاء المخصصة مع بيانات بنوع محدد



إنشاء تسلسل هرمي للأخطاء يسمح بتحديد المشكلة بدقة ونقل بيانات إضافية:



// الفئة الأساسيةclass AppError extends Error {  constructor(    message: string,    public readonly code: number,    public readonly isOperational: boolean = true  ) {    super(message);    this.name = 'AppError';  }}

// أخطاء متخصصةclass ValidationError extends AppError { constructor( message: string, public readonly field: string, public readonly invalidValue: unknown ) { super(message, 400); this.name = 'ValidationError'; }}

class NotFoundError extends AppError { constructor(entity: string, id: string) { super(`${entity} بالمعرف ${id} غير موجود`, 404, false); this.name = 'NotFoundError'; }}

// الاستخدامfunction findUser(id: string): User { if (!validateId(id)) { throw new ValidationError('معرف غير صالح', 'id', id); } const user = db.findUser(id); if (!user) { throw new NotFoundError('المستخدم', id); } return user;}

try { const user = findUser('123');} catch (error) { if (error instanceof NotFoundError) { // error.code === 404, error.message يحتوي على الوصف console.warn(error.message); } else if (error instanceof ValidationError) { // error.field و error.invalidValue متاحان console.error(`خطأ في الحقل ${error.field}: ${error.message}`); } else if (error instanceof AppError) { console.error(`خطأ في التطبيق (الكود ${error.code}): ${error.message}`); }}


3. الاتحادات المميزة لمعالجة الأخطاء



يسمح هذا النمط بمعالجة نتائج العمليات دون استثناءات، باستخدام اتحاد الأنواع مع مميز:



// نوع النتيجة مع مميزtype Result<T, E = Error> =   | { success: true; data: T }  | { success: false; error: E };

// دالة تُرجع Resultfunction safeDivide(a: number, b: number): Result<number, string> { if (b === 0) { return { success: false, error: 'القسمة على صفر' }; } return { success: true, data: a / b };}

// الاستخدامconst result = safeDivide(10, 0);

if (result.success) { // TypeScript يعلم أن result.data من النوع number console.log(`النتيجة: ${result.data}`);} else { // result.error من النوع string console.error(`خطأ: ${result.error}`);}

// مثال أكثر تعقيدًا مع أخطاء مخصصةtype UserResult = Result<

المدونات

توصيات الكتب