الانتقال إلى المحتوى الرئيسي
الوحدة 5 · الدرس 1 من 29/14 في الدورة~15 min
دروس الوحدة (1/2)

نوع الحرس

يعد تضييق الكتابة أحد أهم المفاهيم في TypeScript. ومع ذلك، في كثير من الأحيان، لا تكون أدوات الحماية من النوع القياسي مثل typeof أو instanceof كافية للكائنات المخصصة المعقدة. هذا هو المكان الذي يأتي فيه النوع المخصص من الحراس.

حراس النوع القياسي

لنبدأ بتلخيص كيفية قيام TypeScript بتضييق نطاق الأنواع باستخدام عوامل تشغيل JavaScript القياسية:

TS
function processInput(val: string | number) {
  if (typeof val === 'string') {
    // Here 'val' is of type string
    console.log(val.toUpperCase());
  } else {
    // Here 'val' is of type number
    console.log(val.toFixed(2));
  }
}

حراس النوع المخصص (is المشغل)

لتحديد نوع حماية مخصص، نقوم بإنشاء دالة تُرجع مسند النوع بالتنسيق parameterName is Type بدلاً من نوع الإرجاع المنطقي القياسي.

يجب أن تقوم الدالة بإرجاع قيمة منطقية (true أو false). إذا أعادت true، فسوف تعرف TypeScript أن المعلمة التي تم تمريرها هي من النوع المحدد.

TS
interface Cat {
  name: string;
  meow(): void;
}

interface Dog {
  name: string;
  bark(): void;
}

// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function makeNoise(pet: Cat | Dog) {
  if (isCat(pet)) {
    // Here TypeScript knows 'pet' is a Cat
    pet.meow();
  } else {
    // Here TypeScript knows 'pet' is a Dog
    pet.bark();
  }
}

السلامة والصب (as مقابل واقيات النوع)

يُجبر تحويل النوع (على سبيل المثال، val as Cat) المترجم على الثقة بالمطور دون أي تحقق حقيقي في وقت التشغيل. إذا كان كائن وقت التشغيل لا يلبي التوقعات، فسوف تفشل التعليمات البرمجية بصمت أو ستطرح استثناءات.

من ناحية أخرى، تقوم حراس النوع المخصص بإجراء فحص قوي وديناميكي لوقت التشغيل، وإبلاغ مترجم TypeScript بأمان ودقة عن نوع المتغير الفعلي:

TS
function processInput(input: unknown) {
  // unsafe casting: could crash if input does not have the split method
  // const str = input as string;
  // console.log(str.split(' '));

  // safe guard
  if (isString(input)) {
    console.log(input.split(' ')); // 100% Safe!
  }
}

جربه بنفسك

التمرين 1: حماية نوع السلسلة

تمرين#ts.m5.l1.e1
المحاولات: 0جارٍ التحميل…

قم بإنشاء وظيفة بسيطة تسمى isString تعمل كحارس نوع مخصص للتحقق مما إذا كانت القيمة غير المعروفة عبارة عن سلسلة.

جارٍ تحميل المحرر…
إظهار التلميح

يجب أن يكون نوع الإرجاع للدالة val عبارة عن سلسلة، ويجب عليك استخدام typeof للتحقق مما إذا كان يساوي "string".

الحل متاح بعد 3 من المحاولات

التمرين 2: حماية نوع المستخدم المتميزة

تمرين#ts.m5.l1.e2
المحاولات: 0جارٍ التحميل…

بالنظر إلى نوعي المستخدم وPremiumUser، اكتب وظيفة حماية النوع هيPremiumUser(user: User): المستخدم PremiumUser الذي يتحقق مما إذا كان المستخدم لديه الدور "المميز".

جارٍ تحميل المحرر…
إظهار التلميح

حدد التوقيع كوظيفة isPremiumUser(user: User): المستخدم PremiumUser وقارن user.role بـ "premium".

الحل متاح بعد 3 من المحاولات

التمرين 3: التحقق من صحة كائن الخطأ المخصص

تمرين#ts.m5.l1.e3
المحاولات: 0جارٍ التحميل…

قم بتطبيق isCustomError(err: غير معروف): err هي وظيفة CustomError التي تتحقق مما إذا كانت القيمة غير المعروفة عبارة عن كائن CustomError غير فارغ يحتوي على مفتاح "الكود".

جارٍ تحميل المحرر…
إظهار التلميح

تحقق أولاً مما إذا كان typeof err هو "object" وليس خاليًا، ثم استخدم عامل التشغيل "in" للتحقق من خاصية "code".

الحل متاح بعد 3 من المحاولات

التمرين 4: حماية نوع المسؤول

تمرين#ts.m5.l1.e4
المحاولات: 0جارٍ التحميل…

بالنظر إلى واجهتين المستخدم (مع دور الخاصية: سلسلة) والمسؤول (توسيع المستخدم والحصول على خاصية adminToken: سلسلة)، اكتب وظيفة حماية النوع المسماة isAdmin التي تقبل مستخدمًا من النوع User وترجع المستخدم الأصلي للنوع هو Admin. يجب على الحارس التحقق مما إذا كان دور المستخدم مساويًا لـ "المسؤول".

جارٍ تحميل المحرر…
إظهار التلميح

حدد التوقيع كوظيفة isAdmin(user: User): المستخدم هو المسؤول وتحقق مما إذا كان user.role === 'admin'.

الحل متاح بعد 3 من المحاولات