narrowing أساسيات تضييق الأنواع (التصدّق وقابلية الإسناد)
آخر تحديث: 2026-10-22
narrowing أساسيات تضييق الأنواع (التصدّق وقابلية الإسناد)
يجمع النوع الاتحادي (union type) عدة احتمالات في متغير واحد، لذا يجب قبل استخدامه أن تعرف ما نوعه في تلك اللحظة بالضبط — وتُسمى عملية تقليص النوع الواسع إلى نوع محدد «التضييق» (narrowing). يحلل TypeScript مسار التحكم (if وswitch وفحوصات التصادق) ويضيّق المتغير تلقائيًا إلى نوع الفرع المطابق، وبعدها فقط يصبح الوصول إلى أعضاء ذلك الفرع وحده آمنًا.
| المجموعة | تضييق الأنواع والتأكيدات |
|---|---|
| النوع | بناء الجملة |
| الوضع الصارم | غير مطلوب |
ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.
📝 الصيغة
function handle(value: string | number | null) {
if (value == null) return; // يستبعد null/undefined بالتضييق
if (typeof value === "string") {
value.toUpperCase(); // value مضيَّق إلى string هنا
} else {
value.toFixed(2); // value مضيَّق إلى number هنا
}
}
⚙️ المعاملات
| == null | يفلتر المساواة المتساهلة (==) كلاً من null وundefined في فحص واحد — وهي الصيغة الأكثر شيوعًا للتضييق نحو القيم غير الفارغة |
|---|---|
| truthiness | فحص التصادق مثل if (value) يستبعد في الوقت نفسه null وundefined و0 و"" وfalse وNaN |
القيمة المُعادة:لا قيمة معادة — التضييق تحليل لمسار التحكم يجري في وقت الترجمة (compile time) ولا يولّد أي شيفرة وقت تشغيل.
▶ مثال
عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:
الناتج:
Hello, guest
Hello, guest
Hello, anonymous
Hello, Ada (length 3)
(مخرجات التشغيل بعد الترجمة؛ الوصول الآمن إلى name.length داخل كل فرع ممكن لأن tsc قد ضيّق name إلى string — في وقت التشغيل لا ترى الشيفرة سوى القيم)
💡 نقاط مهمة
ℹ️ معلومة التضييق سلوك يقتصر على وقت الترجمة تمامًا: يتتبع TypeScript الأنواع على طول مسارات التنفيذ (تحليل مسار التحكم)، ولا تحتوي شيفرة JS الناتجة على أي «شيفرة تضييق».
⚠️ تنبيه فحص التصادق يمسّ القيم falsy المشروعة أيضًا: 0 و"" وfalse تُستبعد جميعها بواسطة if (value). عندما تكون 0 قيمة عمل صالحة (مثل السعر أو الكمية)، استخدم value != null أو فحص typeof صريحًا بدلًا من ذلك.
💡 تلميح التضييق أكثر موثوقية مع المتغيرات المحلية وconst؛ أما تضييق خصائص الكائنات فقد يفسد بعد استدعاء دالة (لا يعرف TS هل عدّلتها الدالة أم لا) — في هذه الحالة انسخ الخاصية إلى متغير محلي أولًا، أو استخدم دالة حارسة للنوع.
🏷️ تضييق الأنواع والتأكيدات ذو صلة
💡 حالات ذات صلة
المزيد من الحالات قادم قريبًا.
📚 دروس ذات صلة
❓ أسئلة شائعة
س ما الفرق بين التضييق وتأكيد النوع (as)؟
ج التضييق يستنتجه المترجم تلقائيًا من الفحوصات التي تكتبها، فتبقى الفحوصات والأنواع متطابقة؛ أما التأكيد فهو إعلان يدوي منك للنوع بلا أي تحقق من المترجم. فضّل التضييق متى أمكن — فالتأكيد الخاطئ لن يعترض عليه المترجم.
س لماذا قد يبقى obj.flag بـ undefined رغم أنني فحصت if (!obj.flag) قبله؟
ج بالنسبة إلى الوصول إلى الخصائص واستدعاءات الدوال — أي وصول قد يكون له آثار جانبية — لا يحافظ TS على التضييق طويلًا؛ فأي استدعاء دالة بينهما قد يغيّر القيمة. الأسلم أن تنسخ القيمة إلى متغير محلي بـ const ثم تفحصها.
س هل يمكن لفحص واحد استبعاد null وundefined معًا؟
ج نعم: value == null (المساواة المتساهلة) يستبعد كليهما معًا؛ ويمكن استخدام value != null للتحقق العكسي من عدم الفراغ. أما المساواة الصارمة === فتتطلب مقارنتين (=== null و=== undefined).