المصفوفات بأنواع مختلفة في TypeScript: دليل كامل مع أمثلة

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

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

ابدأ الدورة

مقدمة: لماذا يعتبر النوع الواحد مملًا؟

\n\n

تخيل: أنت تكتب كودًا بلغة TypeScript وفجأة تواجه موقفًا حيث يجب على المصفوفة تخزين بيانات من أنواع مختلفة. على سبيل المثال، قائمة حيث كل عنصر إما string أو number. أو توبل (tuple) من اسم (نص) وعمر (رقم).

\n\n

يتساءل العديد من المبتدئين (وليس فقط): «كيف أعلن عن مصفوفة بعدة أنواع في TypeScript؟» هذا السؤال حصد آلاف المشاهدات على Stack Overflow - وليس بدون سبب. TypeScript صارم مع الأنواع، لكنه في نفس الوقت يوفر أدوات مرنة لمثل هذه الحالات.

\n\n

في هذه المقالة، سنستعرض جميع الطرق للعمل مع المصفوفات ذات الأنواع المختلطة: من أنواع الاتحاد (union types) البسيطة إلى التوبل (tuples) والأدوية (generics). ستتعرف متى تستخدم أي نهج، وكيف لا تقع في فخ any.

\n\n

1. أنواع الاتحاد (Union Types): الطريقة الأبسط

\n\n

الخيار الأكثر وضوحًا هو استخدام union type (نوع الاتحاد). هذا عندما تقول: «يمكن للمصفوفة أن تحتوي على عناصر من نوع string أو number».

\n\n
// مصفوفة يمكن أن تحتوي على نصوص أو أرقام\nconst mixedArray: (string | number)[] = ['hello', 42, 'world', 100];\n\n// كتابة بديلة (مكافئة)\nconst mixedArray2: Array<string | number> = ['hello', 42, 'world', 100];
\n\n

هنا (string | number)[] تعني: «مصفوفة، كل عنصر فيها هو نص أو رقم». سيتحقق TypeScript من أنك لا تحاول إضافة، على سبيل المثال، قيمة منطقية (boolean) أو كائن (object).

\n\n

متى يكون هذا مناسبًا؟

\n
    \n
  • عندما لا يكون ترتيب العناصر مهمًا، بل المهم هو فقط مجموعة الأنواع المسموح بها.
  • \n
  • عندما تعمل مع API يعيد مصفوفة من بيانات غير متجانسة.
  • \n
  • عندما تخزن قائمة من المعرفات (أرقام) والأسماء (نصوص) في مصفوفة واحدة.
  • \n
\n\n

المأزق

\n

عند استخدام أنواع الاتحاد، لا يمكنك ضمان أن في الموضع الأول سيكون نصًا وفي الموضع الثاني سيكون رقمًا. الكتابة (typing) تقول فقط: «هناك نصوص وأرقام في المصفوفة، لكن الترتيب غير معروف».

\n\n
const arr: (string | number)[] = [1, 'hello'];\n// TypeScript لا يعرف: arr[0] هو number أم string؟\nconst first = arr[0]; // النوع: string | number\n// لاستخدامه كرقم، تحتاج إلى تضييق النوع:\nif (typeof first === 'number') {\n    console.log(first.toFixed(2));\n}
\n\n

2. التوبل (Tuples): عندما يكون الترتيب مهمًا

\n\n

إذا كنت بحاجة إلى أن يكون للمصفوفة هيكل ثابت - على سبيل المثال، الأول نص، والثاني رقم، والثالث قيمة منطقية - استخدم التوبل (tuple types).

\n\n
// توبل: [نص، رقم، منطقي]\nconst person: [string, number, boolean] = ['Alice', 30, true];\n\n// توبل مع تسميات (labels) - أكثر قابلية للقراءة\nconst product: [name: string, price: number, inStock: boolean] = ['Laptop', 1200, true];
\n\n

التوبل تثبت بشكل صارم عدد العناصر والنوع في كل موضع. إذا حاولت تعيين قيمة من نوع خاطئ أو إضافة عنصر إضافي - سيعطي TypeScript خطأ.

\n\n

عناصر Rest في التوبل

\n

منذ TypeScript 4.0، أصبح من الممكن تحديد عناصر rest في التوبل. هذا مفيد عندما يكون جزء من الهيكل ثابتًا والباقي متغيرًا:

\n\n
// العنصر الأول نص، والباقي أرقام\nconst data: [string, ...number[]] = ['scores', 95, 87, 92];\n\n// يمكن الدمج\nconst logEntry: [timestamp: Date, ...messages: string[]] = [new Date(), 'info', 'user logged in'];
\n\n

3. Type Alias للمصفوفات المعقدة

\n\n

عندما يصبح هيكل المصفوفة معقدًا، من المناسب استخراج النوع في alias (اسم مستعار) منفصل. هذا يحسن قابلية قراءة الكود ويسمح بإعادة استخدام النوع.

\n\n
type UserEntry = [id: number, name: string, email: string, isActive: boolean];\n\nconst users: UserE                

المدونات

توصيات الكتب