try / catch معالجة الأخطاء وتضييق catch

آخر تحديث: 2026-10-22

try / catch معالجة الأخطاء وتضييق catch

في معالجة أخطاء TS نقطة ألم بارزتان: الأولى أن err في catch من نوع unknown في الوضع الصارم (فـ JS يمكنها رمي أي قيمة ولا يجرؤ المترجم على افتراض أنها Error) ولا يمكن لمس .message قبل التضييق؛ والثانية أن «احتمال الرمي» لا يظهر في توقيع النوع فلا سبيل للمستدعي لمعرفته. والحلول: ضيّق unknown عبر instanceof؛ وبالنسبة إلى «الفشل المتوقع» انتقل إلى نمط Result الذي يكتب النجاح والفشل في نوع الإرجاع مباشرة.

المجموعةالإعداد والتطبيق
النوعبناء الجملة
الوضع الصارمغير مطلوب

ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.

📝 الصيغة

// 1) تضييق unknown
try {
  risky();
} catch (err: unknown) {
  if (err instanceof Error) console.log(err.message);
  else console.log("unknown throw:", err);
}

// 2) نمط Result: نوع اتحادي يعبر عن النجاح أو الفشل
type Result<T> = { ok: true; value: T } | { ok: false; error: string };

function attempt<T>(fn: () => T): Result<T> {
  try { return { ok: true, value: fn() }; }
  catch { return { ok: false, error: "failed" }; }
}

⚙️ المعاملات

unknownنوع متغير catch (وهو الافتراضي في الوضع الصارم): يتسع لأي شيء لكن يجب تضييقه قبل الاستخدام — ومن هنا تأتي الأمانة
instanceofأشيع وسائل التضييق: بعد err instanceof Error يمكن الوصول إلى .message/.stack؛ ويعمل مع أصناف الأخطاء المخصصة أيضًا
Result<T>نوع إرجاع مكتوب يدويًا: { ok: true; value: T } | { ok: false; error }. يجب على المستدعي فحص ok أولًا؛ ولا يمكن لكل فرع الوصول إلا إلى value أو error

القيمة المُعادة:نوع إرجاع نمط Result اتحاد قابل للتمييز: لا توجد value إلا عندما يكون ok هو true ولا error إلا عندما يكون false — فيُرمَّز «احتمال الفشل» في النوع ذاته، ولا يمر التجميع للمستدعي ما لم يعالج فرع الفشل.

▶ مثال

عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:

الناتج:

caught RangeError: not a positive integer: abc
7 0
{"ok":true,"value":42}
failed: invalid input

(مخرجات التشغيل بعد الترجمة؛ لا يمكن الوصول إلى .message إلا بعد التضييق بـ instanceof — والوصول المباشر إلى err.message من دونه يعطي error TS18046)

💡 نقاط مهمة

ℹ️ معلومة تسمح JS برمي أي قيمة (أرقام وسلاسل وكائنات)، لذا يجعل TS نوع err في catch هو unknown لا Error — وهذه حماية من useUnknownInCatchVariables (المضمّنة في strict) تمنعك من الاعتماد بلهفة على خاصية .message قد لا توجد.
💡 تلميح ليس instanceof وحده وسيلة تضييق: فـ typeof err === "string" و"message" in err والحراسات المخصصة مثل isApiError(err) كلها تعمل؛ واحتفظ بفرع احتياطي أخير يعالج حالات «لا تطابق أي شيء» لكي تغطي أي قيمة مرموة.
⚠️ تنبيه يطيل نمط Result شيفرة المستدعي (فكل موضع استدعاء يجب أن يفحص ok). والتسوية الشائعة: الإبقاء على الاستثناءات في مسار العمل الأساسي، وتحويل حدود النظام (تحليل مدخلات المستخدم، استدعاء واجهات خارجية) إلى Result، تاركًا «الفشل المتوقع» لمعالجة صريحة من المستدعي.
المزيد من الحالات قادم قريبًا.

📚 دروس ذات صلة

❓ أسئلة شائعة

س لماذا لا يمكنني استخدام err.message مباشرة في catch؟
ج لأن نوع err هو unknown (فـ JS يمكنها رمي أي قيمة ومنها السلاسل) ولا يضمن المترجم وجود .message. ضيّق أولًا — err instanceof Error أو typeof err === "string" أو "message" in err — ثم اصل إليها بأمان.
س كيف أضيّق أصناف الأخطاء المخصصة؟
ج عرّف صنفك الخاص بامتداد Error (مثل ValidationError) ثم ضيّق في catch بـ err instanceof ValidationError لتصل إلى الحقول المخصصة (مثل err.field). ويمكن أن تتعدد فروع التضييق في try واحد مرتبة من الأخص إلى الأعم.
س متى أرمي استثناءً ومتى أعيد Result؟
ج الاستثناءات تناسب «الحالات غير المتوقعة» (أخطاء برمجية، انقطاع شبكة مفاجئ) التي لا ينبغي للمستدعي معالجتها في الغالب؛ وResults تناسب «الفشل المتوقع» (تحليل المدخلات، التحقق من النماذج) الذي يجب على المستدعي معالجته — والنوع يفرض ذلك. المعيار: هل من خطوة تالية مفيدة للمستدعي بعد هذا الفشل؟
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%