assertNever فحص الاستنفاد
آخر تحديث: 2026-10-22
assertNever فحص الاستنفاد
فحص الاستنفاد تأمين في وقت الترجمة يضمن «معالجة كل عضو من أعضاء النوع الاتحادي». جوهره حيلة assertNever: التصريح بنوع معامل فرع default في switch بوصفه never — فإن سقط عضو فسيظل قادرًا على المرور، فلن يصبح المعامل never، ويرفض المترجم فورًا.
| المجموعة | تضييق الأنواع والتأكيدات |
|---|---|
| النوع | بناء الجملة |
| الوضع الصارم | غير مطلوب |
ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.
📝 الصيغة
function assertNever(x: never): never {
throw new Error("Unhandled: " + JSON.stringify(x));
}
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "square": return shape.side ** 2;
default:
return assertNever(shape); // خطأ تصريف هنا إذا سقط أحد الفروع
}
}
⚙️ المعاملات
| x: never | النوع never نوع فرعي من كل الأنواع ولا أعضاء له — لا يرضى المعامل بالوسيط بوصفه never إلا بعد معالجة كل الفروع وفراغ النوع المتبقي |
|---|
القيمة المُعادة:يعيد assertNever النوع never (لا يعود بشكل طبيعي أبدًا؛ يرمي في وقت التشغيل)؛ أما «عائده» في وقت الترجمة فهو رسالة الخطأ: Argument of type 'X' is not assignable to parameter of type 'never'.
▶ مثال
عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:
الناتج:
3.14
9
(مخرجات التشغيل بعد الترجمة: الفروع مكتملة حاليًا فلا يبلغ التنفيذ assertNever أبدًا. وإذا أُضيف kind: "triangle" إلى Shape دون فرع، أبلغ tsc في سطر default بالخطأ "Argument of type '{ kind: "triangle"; ... }' is not assignable to parameter of type 'never'")
💡 نقاط مهمة
ℹ️ معلومة المبدأ: عند التبديل switch على اتحاد يزيل TS الأعضاء المعالَجة من النوع تدريجيًا. بعد معالجة الجميع يصبح shape من نوع never ويُسند إلى معامل never؛ وسقوط عضو واحد يُفشل الإسناد، ويشير الخطأ إلى سطر default تحديدًا.
💡 تلميح أكبر عائد لفحص الاستنفاد يظهر عند إضافة عضو جديد للاتحاد: لا حاجة إلى بحث شامل في الشيفرة — يسرد المترجم كل switch صار ناقصًا دفعة واحدة.
⚠️ تنبيه يعتمد فحص الاستنفاد على الأنواع الاتحادية القابلة للتمييز: يجب أن يكون حقل التمييز من نوع حرفي. فالتبديل على حقل من نوع string أو استخدام سلسلة if-else يمنعان المترجم من الحكم على الاستنفاد.
🏷️ تضييق الأنواع والتأكيدات ذو صلة
💡 حالات ذات صلة
المزيد من الحالات قادم قريبًا.
📚 دروس ذات صلة
❓ أسئلة شائعة
س ألا يمكنني كتابة switch مكتمل دون assertNever؟
ج يستطيع noImplicitReturns ووضع strict كشف «مسارات بلا قيمة معادة»، لكنه لا يكشف «حالة منطقية غير معالَجة» (مثل فرع يعيد بهدوء قيمة افتراضية). assertNever يحوّل «الحالة المنسية» إلى خطأ ترجمة صارم.
س هل يصلح فحص الاستنفاد مع سلاسل if-else؟
ج نعم — استدعِ assertNever(x) في else الأخيرة؛ الآلية نفسها. ومع ذلك فإن switch أقروى وتتعامل بسلاسة أكبر مع تحليل حقول التمييز، لذا فضّلها.
س هل يُنفَّذ assertNever في وقت التشغيل فعلًا؟
ج ليس ما دامت الشيفرة تُصان صحيحًا — فهو لا يبلغ إلا في سيناريو الفرع المنسي الذي يكون المترجم قد منعه أصلًا. إبقاء throw خلفي برمجة دفاعية: إذا خالفت بيانات التشغيل الأنواع المعلنة (كبيانات مخزن قديم) فستظهر مبكرًا بدلًا من السير الصامت في فرع خاطئ.