0Pricing
TypeScript Academy · درس

التحقق من اكتمال الحالات باستخدام never

اكتشفوا الحالات غير المعالجة أثناء التجميع باستخدام never

التحقق من اكتمال الحالات باستخدام never درس مجاني في TypeScript Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في TypeScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة TypeScript Academy 4 دروس في المجموع.

مشكلة اكتمال الحالات

عند إضافة عضو جديد إلى الاتحاد، من السهل نسيان معالجته في أحد المواضع. ويحوّل التحقق من اكتمال الحالات هذا السهو إلى خطأ في وقت الترجمة.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

// If we add "triangle" later, we want every switch to complain.

النوع never

يمثّل النوع never قيمًا لا يمكن أن تحدث مطلقًا. وإذا عولجت كل الحالات، فستكون قيمة فرع default من النوع never.

function fail(): never {
  throw new Error("unreachable");
}
// never is assignable to nothing except never itself.

الإسناد إلى never في الحالة الافتراضية

في فرع default، أسند القيمة إلى متغير من النوع never. فإذا عولجت جميع الأنواع المختلفة، ينجح التجميع؛ وإلا فسيظهر خطأ.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default:
      const _exhaustive: never = s;
      return _exhaustive;
  }
}
console.log(area({ kind: "square", side: 3 }));

ماذا يحدث عند نسيان إحدى الحالات؟

إذا أضفت عضو triangle ونسيت حالته، فلن يعود s في الحالة الافتراضية من النوع never، ولذلك يفشل الإسناد في وقت الترجمة.

// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to never

الدالة المساعدة assertNever

تجمع دالة assertNever القابلة لإعادة الاستخدام هذا النمط في موضع واحد. فهي تقبل never وتطرح خطأ، موضحةً أن الفرع لا ينبغي الوصول إليه.

function assertNever(value: never): never {
  throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);

استخدام assertNever في switch

استدعِ assertNever(s) في الحالة الافتراضية. فهي تفرض اكتمال الحالات في وقت الترجمة، وتوفر خطأ واضحًا في وقت التشغيل إذا تم الوصول إليها.

function assertNever(value: never): never {
  throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default: return assertNever(s);
  }
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));

أمان وقت الترجمة في مقابل أمان وقت التشغيل

يلتقط فحص never الحالات المفقودة قبل تشغيل الشيفرة، كما يحميك الخطأ المطروح إذا تجاوز شيء ما فحص الأنواع في وقت التشغيل.

function assertNever(x: never): never {
  throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");

اكتمال الحالات دون default

إذا كانت لدالتك نوع إرجاع صريح وكان switch يغطي كل الحالات، فيمكن لـ TypeScript أيضًا اكتشاف غياب قيمة الإرجاع، وهو شكل آخر من التحقق من اكتمال الحالات.

type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
  switch (l) {
    case "red": return "green";
    case "yellow": return "red";
    case "green": return "yellow";
  }
  // No default needed; all cases return.
}
console.log(next("red"));

اكتمال الحالات باستخدام سلاسل if/else

تنطبق الفكرة نفسها على if/else. فبعد معالجة كل نوع مختلف، يتلقى else النهائي قيمة من النوع never.

function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function name(s: Shape): string {
  if (s.kind === "circle") return "circle";
  else if (s.kind === "square") return "square";
  else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));

لماذا يُعد never الأداة المناسبة؟

بما أن never غير قابل للإسناد إلى أي نوع، فإن أي نوع مختلف متبقٍّ يؤدي إلى فشل الإسناد. وهذا يجعل never الكاشف المثالي للحالات غير المعالجة.

// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");

اكتمال الحالات كشبكة أمان عند إعادة الهيكلة

مع استخدام assertNever في كل المواضع، تؤدي إضافة عضو إلى الاتحاد إلى إنشاء قائمة واضحة من أخطاء الترجمة تشير بدقة إلى كل موضع يجب تحديثه.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
  switch (s) {
    case "idle": return "Idle";
    case "busy": return "Busy";
    default: return assertNever(s);
  }
}
console.log(render("idle"));

تحقق سريع: اكتمال الحالات

اختبر فهمك للتحقق من اكتمال الحالات.

مراجعة: اكتمال الحالات باستخدام never

تعلّمت إسناد القيمة الافتراضية إلى never، أو تمريرها إلى assertNever، كي يُجبرك المترجم على معالجة كل نوع مختلف. وبهذا تتحول الحالات المنسية إلى أخطاء في وقت الترجمة.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
  switch (s.kind) {
    case "circle": return s.radius;
    case "square": return s.side;
    default: return assertNever(s);
  }
}
console.log(f({ kind: "circle", radius: 5 }));

الأسئلة الشائعة

هل درس «التحقق من اكتمال الحالات باستخدام never» مجاني؟

نعم — نص درس «التحقق من اكتمال الحالات باستخدام never» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة TypeScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة TypeScript Academy 4 دروس في المجموع.

ماذا ستتعلم في «التحقق من اكتمال الحالات باستخدام never»؟

اكتشفوا الحالات غير المعالجة أثناء التجميع باستخدام never تتمرن على TypeScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ TypeScript Academy؟

لا تُشترط خبرة سابقة. TypeScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «التحقق من اكتمال الحالات باستخدام never»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس TypeScript Academy هذا؟

نعم. كل درس في TypeScript Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. بناء الاتحادات المميّزة
  2. تضييق النوع اعتمادًا على المميّز
  3. التحقق من اكتمال الحالات باستخدام never
  4. نمذجة آلات الحالات
← العودة إلى TypeScript Academy