in تضييق الأنواع بمعامل in

آخر تحديث: 2026-10-22

in تضييق الأنواع بمعامل in

يتحقق معامل in من وجود اسم خاصية على كائن ما، ويستغل TypeScript ذلك ليضيّق النوع الاتحادي إلى العضو الذي يمتلك تلك الخاصية. عندما لا يشارك أعضاء الاتحاد حقلًا مشتركًا للتمييز ويكونون واجهات (لا يصلح معها instanceof)، يكون in أيسر وسائل للتمييز البنيوي.

المجموعةتضييق الأنواع والتأكيدات
النوععامل
الوضع الصارمغير مطلوب

ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.

📝 الصيغة

interface Bird { fly: () => void }
interface Fish { swim: () => void }

function move(animal: Bird | Fish) {
  if ("swim" in animal) {
    animal.swim();   // مضيَّق إلى Fish
  } else {
    animal.fly();    // مضيَّق إلى Bird
  }
}

⚙️ المعاملات

"key" in objفي وقت التشغيل يتحقق مما إذا كان key خاصيةً في obj (بما في ذلك سلسلة النماذج الأولية) ويعيد قيمة منطقية؛ ويضيّق TS في الوقت نفسه obj إلى عضو الاتحاد الذي يحتوي تلك الخاصية

القيمة المُعادة:يعيد تعبير in قيمة منطقية؛ ويحدث التضييق في وقت الترجمة اعتمادًا على التبادلية بين خصائص أعضاء الاتحاد (امتلاك خاصية أو الانعدام).

▶ مثال

عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:

الناتج:

bubble...
it swims
flap!
it flies

(مخرجات التشغيل بعد الترجمة؛ نجاح الفحص النوعي للوصول إلى animal.swim() سببه أن تضييق in قد ثبّت animal بوصفها Fish — التضييق مضمون ساكنًا بواسطة tsc، وفي وقت التشغيل لا توجد سوى القيم)

💡 نقاط مهمة

ℹ️ معلومة يفحص in «وجود الخاصية من عدمه» بما في ذلك الخصائص الموروثة عبر سلسلة النماذج الأولية. الكائنات العادية تمتلك خصائص مدمجة مثل toString وconstructor، لذا استخدم أسماء حقول عملك الخاصة في الفحص.
⚠️ تنبيه يعتمد تضييق in على «تبادل الخصائص»: إذا كان عضوان يمتلكان حقلًا بالاسم نفسه (يختلفان في النوع فقط) فلن يساعد in كثيرًا. في هذه الحالة انتقل إلى نوع اتحادي قابل للتمييز (حقل تمييز يأخذ قيمًا حرفية مختلفة).
💡 تلميح الـ in هو أيضًا البنية الجوهرية للأنواع المُعَيَّنة (mapped types) بالصيغة [K in keyof T]، لكن ذلك استخدام على مستوى الأنواع؛ تتناول هذه المدخلة in بوصفه معامل وقت تشغيل مع تضييق في وقت الترجمة.
المزيد من الحالات قادم قريبًا.

📚 دروس ذات صلة

❓ أسئلة شائعة

س كيف أختار بين تضييق in والأنواع الاتحادية القابلة للتمييز؟
ج إن أمكنك تصميم حقل حرفي مختلف لكل عضو (مثل type/status/kind) فاستخدم النوع الاتحادي القابل للتمييز — فهو أوضح ويدعم فحص الاستنفاد؛ وعندما يأتي الاتحاد من طرف ثالث دون حقل تمييز، ميّز بنيويًا باستخدام in.
س هل قد تخدع الخصائص الاختيارية تضييق in؟
ج نعم. الخاصية الاختيارية flag?: boolean قد تكون غائبة فعلًا عن الكائن، فكون flag in obj === false لا يثبت أن الكائن من العضو الآخر. تأكد قبل الاعتماد على in أن الخاصية «واجبة» في عضو و«غائبة» في البقية.
س هل يظل in يضيّق بشكل صحيح بعد حذف خاصية بـ delete؟
ج نعم — بعد delete obj.key تصبح نتيجة in في وقت التشغيل false ويضيّق TS النوع إلى العضو الخالي من تلك الخاصية. لكن تذكر أن strict في TS يجعل حذف خاصية واجبة خطأً في الترجمة أصلًا، تحقيقًا لتوافق نوع الإعلان مع الواقع في وقت التشغيل.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%