جملة switch في TypeScript هي switch في JavaScript مع فحص الأنواع. تقارن قيمة مع كل case بـ ===، وتنفّذ الفرع المطابق، وتتوقف عند break أو return. وتضيّق TypeScript القيمة المفحوصة داخل كل حالة، ويمكنها التحقق من معالجة كل قيمة ممكنة.
التسميات المكدسة (case "sat": case "sun":) تشترك في فرع واحد. وينهي return الدالة، فلا حاجة إلى break بعده.
الصياغة
switch (expression) {
case value1:
// runs when expression === value1
break;
case value2:
case value3:
// runs for value2 or value3
break;
default:
// runs when nothing else matched
}
- تستخدم المطابقة المساواة الصارمة
===: الحالةcase 1لا تطابق النص"1". - دون
breakأوreturnأوthrowيستمر التنفيذ إلى الحالة التالية (fallthrough). defaultاختياري ويمكن وضعه في أي مكان، وإن كان المعتاد وضعه في النهاية.- قيمة
caseتستطيع TypeScript إثبات أنها لا تطابق أبدًا هي الخطأ TS2678. لمعامل نوعه"a" | "b"تبلّغcase "c":الرسالةType '"c"' is not comparable to type '"a" | "b"'.، وهذا يلتقط الأخطاء الإملائية في تسميات الحالات.
التضييق داخل كل حالة
في كل case تعرف TypeScript أي قيمة طابقت وتضيّق النوع. وهذا أكثر فائدة مع discriminated union: استخدم خاصية الوسم المشتركة في switch، فترى كل حالة المتغير المطابق بخصائصه الخاصة.
لا يُترجم shape.radius إلا في حالة "circle". وخارجها قد يكون shape مستطيلًا لا يملك radius. لا يوجد default، ومع ذلك تجتاز الدالة فحص الأنواع على أنها تعيد number، لأن TypeScript ترى أن الحالات الثلاث تغطي كل قيم kind. وتجد أنماطًا أخرى مبنية على ذلك في صفحة discriminated unions.
switch شامل مع never
تتوقف الدالة السابقة عن الترجمة إذا أُضيف شكل رابع دون حالة له (TS2366، قيمة مُعادة مفقودة). لكن هذا يعمل فقط عندما تعيد الدالة قيمة. ولضمان يعمل أيضًا في كود void ويعطي رسالة أوضح، أضف default يسند القيمة إلى never:
index.ts(14,19): error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
بعد الحالات المعالَجة، النوع الوحيد المتبقي لـ shape هو متغير المثلث، ولا يمكن إسناده إلى never. والخطأ يسمّي بالضبط ما هو مفقود. أضف case "triangle": return (shape.base * shape.height) / 2; فيرى default النوع never، ويُترجم الكود ويطبع 9. وما زال throw يحمي من البيانات الخاطئة وقت التشغيل، مثل kind قادم من JSON لم تتوقعه الأنواع.
كثير من المشاريع تغلّف الفحص في دالة مساعدة:
والتقنية نفسها تعمل مع enums: استخدم قيمة الـ enum في switch ومرّرها إلى assertNever في default.
switch (true) للنطاقات والشروط
يقارن switch القيم، فالنطاقات تحتاج إلى حيلة: استخدم true في switch واكتب شرطًا في كل case. ومنذ TypeScript 5.3 تضيّق هذه الشروط الأنواع كما تفعل جمل if.
تُختبر الحالات بالترتيب، فضع الأكثر تحديدًا أولًا. أما هل يُقرأ هذا أفضل من if / else if فمسألة ذوق؛ السلوك واحد.
الانتقال إلى الحالة التالية وbreak
الحالة التي فيها كود دون break أو return أو throw تنتقل إلى الحالة التالية. وهذا خطأ برمجي في أغلب الأحيان. خيار المترجم noFallthroughCasesInSwitch (ليس جزءًا من strict) يحوّله إلى الخطأ TS7029، Fallthrough case in switch.، مع السماح بالتسميات الفارغة المكدسة.
الانتقال المقصود بهذا الشكل يعمل، لكن مع تفعيل noFallthroughCasesInSwitch يجب إعادة كتابته، مثلًا بفحوص if منفصلة. وهذا عادةً أوضح على أي حال.
المتغيرات داخل الحالات
جسم switch كله كتلة واحدة، فالـ const المعرّف في حالة يكون مرئيًا في الحالات الأخرى (وإعادة تعريفه خطأ). ضع الحالة بين أقواس معقوصة لتعطيها نطاقها الخاص:
دون الأقواس يكون const unit الثاني خطأ الترجمة TS2451، Cannot redeclare block-scoped variable 'unit'.
switch أم البحث في كائن
عندما تحوّل كل حالة قيمة إلى قيمة أخرى فقط، يكون الكائن المعرّف بنوع Record أقصر، وتتحقق TypeScript من وجود كل مفتاح:
حذف مفتاح خطأ ترجمة، وهذا يعطي الشمولية نفسها التي يعطيها فحص never. واحتفظ بـ switch للحالات التي تنفّذ منطقًا مختلفًا، أو تضيّق متغيرات union، أو تعود مبكرًا.
الأسئلة الشائعة
كيف أكتب جملة switch في TypeScript؟
كما في JavaScript تمامًا: switch (value) { case "a": ...; break; default: ... }. تُقارن الحالات بـ ===. وتضيف TypeScript فحوصًا: قيمة case لا يمكن أن تطابق النوع المفحوص أبدًا تكون خطأ (TS2678)، وداخل كل حالة يُضيَّق المتغير المفحوص إلى تلك الحالة.
كيف أجعل switch شاملًا في TypeScript؟
أضف default يسند القيمة إلى متغير من النوع never: default: { const unreachable: never = value; throw new Error(...) }. عندما يُعالَج كل عضو في union تكون القيمة هناك never ويُترجم الكود. وعندما يغيب أحدها يبلّغ المترجم عن العضو الغائب (TS2322).
كيف أعالج عدة حالات بالكود نفسه في switch في TypeScript؟
ضع التسميات بعضها فوق بعض دون كود بينها: case "sat": case "sun": return "weekend";. الحالات الفارغة تنتقل إلى الحالة التالية. والخيار noFallthroughCasesInSwitch لا يبلّغ إلا عن الحالات التي فيها كود دون break أو return، فتبقى التسميات المكدسة مسموحة.
هل يضيّق switch (true) الأنواع في TypeScript؟
نعم، منذ TypeScript 5.3. في switch (true) { case typeof x === "string": ... } يُضيَّق x إلى string داخل تلك الحالة، كما يحدث في if. وهو بديل مقروء لسلسلة if/else if تفحص نطاقات أو أنواعًا.