فحص أنواع الواجهات في TypeScript: الأسئلة الشائعة والإجابات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا لا تعمل الواجهات أثناء وقت التشغيل؟

\n\n

مرحباً يا صديقي! إذا كنت قد كتبت أي كود في TypeScript، فبالتأكيد واجهت هذا الموقف: تقوم بإنشاء واجهة مثالية، وتصف جميع الحقول، وتفحص الأنواع في مرحلة التجميع — ثم تكتشف فجأة أنه في وقت التشغيل (runtime) يتصرف الكود كما لو أن الواجهات غير موجودة. هل هذا مألوف؟ 🎯

\n\n

هذا أحد أكثر الأسئلة شيوعاً على Stack Overflow: "Interface type check with TypeScript" — آلاف المشاهدات، ومئات الإجابات. ولا عجب، لأن TypeScript يمسح الواجهات أثناء التجميع. على عكس الفئات، الواجهات هي مجرد بنية تعريفية للمطور والمترجم. في JavaScript، لا وجود لها.

\n\n

في هذه المقالة، سنتعرف على كيفية تجاوز هذا القيد، ونتعلم كيفية التحقق من مطابقة الكائن لواجهة في وقت التشغيل، ونجيب على أكثر الأسئلة شيوعاً. هيا بنا! 🚀

\n\n

لماذا نريد فحص الواجهات أصلاً؟

\n\n

تخيل: تحصل على بيانات من API، أو من نموذج، أو من WebSocket. أنت متأكد من أنها تطابق واجهة User، ولكن فجأة يأتي كائن بدون حقل email أو بنوع خاطئ. إذا لم تفحص — سيتعطل الكود الخاص بك مع خطأ. واجهات TypeScript تفحص فقط في مرحلة التطوير، وليس في الإنتاج. لذلك، نحتاج إلى فحوصات وقت التشغيل.

\n\n

المشكلة: الواجهات غير موجودة في وقت التشغيل

\n\n

في TypeScript، الواجهات هي "سكر نحوي" للكتابة الثابتة. عندما تقوم بتجميع الكود، تختفي الواجهات. إليك مثال بسيط:

\n\n
interface User {\n  name: string;\n  age: number;\n}\n\nconst data: unknown = JSON.parse('{"name": "أليس"}');\nif (data instanceof User) { // ❌ خطأ! User هي واجهة، وليست فئة\n  console.log(data.name);\n}
\n\n

سيقول المترجم: 'User' only refers to a type, but is being used as a value here. هذا هو الفخ الرئيسي للمبتدئين. لكن لا تقلق — هناك عدة طرق مثبتة لتجاوز هذا.

\n\n

الطريقة 1: أدوات حماية الأنواع المخصصة (User-Defined Type Guards)

\n\n

الطريقة الأكثر شيوعاً وأناقة هي كتابة دالة حماية نوع. تفحص بنية الكائن وتعيد true/false، و TypeScript "يفهم" أنه داخل الكتلة التي تحتوي على true، الكائن يطابق الواجهة بالتأكيد.

\n\n
interface User {\n  name: string;\n  age: number;\n  email?: string; // حقل اختياري\n}\n\nfunction isUser(obj: unknown): obj is User {\n  if (typeof obj !== 'object' || obj === null) return false;\n\n  const user = obj as Record<string, unknown>;\n  return (\n    typeof user.name === 'string' &&\n    typeof user.age === 'number' &&\n    (user.email === undefined || typeof user.email === 'string')\n  );\n}\n\n// مثال على الاستخدام\nconst data: unknown = JSON.parse('{"name": "بوب", "age": 30}');\n\nif (isUser(data)) {\n  // الآن TypeScript يعلم أن data هي User\n  console.log(data.name.toUpperCase()); // ✅ يعمل\n}
\n\n

المزايا: تحكم كامل، استنتاج الأنواع بشكل صحيح، سهولة التوسيع.
\nالعيوب: تحتاج إلى كتابتها يدوياً لكل واجهة (لكن هناك مكتبات!)

\n\n

ما هو obj is User؟

\n\n

هذا هو بناء جملة حماية النوع. يخبر TypeScript: "إذا أعادت الدالة true، فيمكن اعتبار الوسيطة obj من النوع User". هذا هو السحر الذي يجعل فحص وقت التشغيل مفيداً للتحليل الثابت.

\n\n

الطريقة 2: استخدام الفئات بدلاً من الواجهات

\n\n

الفئات هي البنية الوحيدة في TypeScript التي تبقى في JavaScript. إذا كنت بحاجة إلى فحص النوع في وقت التشغيل، يمكنك استبدال الواجهة بفئة مع التحقق عبر instanceof.

\n\n
class User {\n  constructor(\n    public name: string,\n    public age: number,\n    public email?: string\n  ) {}\n}\n\nconst data = new User('تشارلي', 25);\nif (data instanceof User) {\n  consol                

المدونات

توصيات الكتب