تصنيف الكائنات في TypeScript 2025: دليل بدون حشو

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

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

ابدأ الدورة

مقدمة: لماذا لا يزال موضوع object literal يفجر Stack Overflow؟

\n\n

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

\n\n

موضوع type definition in object literal in TypeScript هو أحد أكثر الاستعلامات شيوعًا على Stack Overflow مع آلاف المشاهدات. وهذا ليس من قبيل الصدفة. البساطة الظاهرة تخفي العديد من الفروق الدقيقة: الفرق بين interface و type، الخصائص الزائدة، الحقول الاختيارية، معدّلات readonly، والمشغل الجديد satisfies.

\n\n

في عام 2025، تقدم TypeScript كثيرًا. ظهرت ميزات تجعل الكود أنظف وأكثر أمانًا. لكن العديد من المطورين لا يزالون يستخدمون أساليب قديمة. دعنا نفهم كيفية كتابة أنواع الكائنات الحرفية بشكل صحيح اليوم، بحيث يكون الكود موثوقًا وقابلاً للقراءة وحديثًا.

\n\n

1. Interface أم Type: ماذا تختار لـ object literal في 2025؟

\n\n

هذا سؤال كلاسيكي يثير نقاشات حامية. دعنا نضع النقاط على الحروف.

\n\n

متى تستخدم interface

\n

Interface هو "المعيار الذهبي" لوصف أشكال الكائنات. يعمل بشكل أفضل مع استنتاج الأنواع، ويعطي رسائل خطأ أكثر وضوحًا، ويدعم declaration merging (دمج التصريحات).

\n\n
// ✅ جيد: interface لـ object literal\ninterface User {\n  name: string;\n  age: number;\n  email?: string; // حقل اختياري\n}\n\nconst user: User = {\n  name: "آنا",\n  age: 28,\n  email: "anna@example.com"\n};
\n\n

متى تستخدم type

\n

Type-aliases لا غنى عنها لأنواع union، وأنواع intersection، والمصفوفات الثابتة (tuples)، والأنواع الشرطية المعقدة. بالنسبة للكائنات البسيطة، تعمل أيضًا ولكن لها قيود.

\n\n
// ✅ جيد: type للاتحاد\ntype Status = "active" | "inactive" | "pending";\n\n// type للكائن مقبول أيضًا، لكنه أقل قابلية للتوسيع\ntype UserType = {\n  name: string;\n  age: number;\n};
\n\n

نصيحة عملية 2025: استخدم interface لواجهات API العامة ووصف أشكال الكائنات. استخدم type للتركيبات المعقدة والأنواع الشرطية وأنواع union. هذه ليست عقيدة، لكنها ممارسة جيدة.

\n\n

2. الخصائص الزائدة (excess property checks): عدو أم صديق؟

\n\n

أحد أكثر أخطاء المبتدئين شيوعًا هو وجود خاصية إضافية في الكائن الحرفي. TypeScript يشتكي، وهذا جيد.

\n\n
interface Config {\n  url: string;\n  timeout?: number;\n}\n\n// ❌ خطأ: خاصية زائدة 'retries'\nconst badConfig: Config = {\n  url: "https://api.example.com",\n  timeout: 5000,\n  retries: 3 // خطأ!\n};
\n\n

لكن هناك ثغرة: إذا قمت بتعيين الكائن عبر متغير، يضعف التحقق. كن حذرًا.

\n\n
const configData = {\n  url: "https://api.example.com",\n  timeout: 5000,\n  retries: 3\n};\n\n// ✅ لا يوجد خطأ (لكن هذا قد يكون غير متوقع)\nconst config: Config = configData;
\n\n

في عام 2025، استخدم satisfies للتحقق الصارم دون فقدان استنتاج الأنواع. سنتحدث عن هذا في القسم التالي.

\n\n

3. مشغل satisfies: الميزة الرئيسية لعام 2025

\n\n

ظهر مشغل satisfies في TypeScript 4.9 وأصبح اختراقًا حقيقيًا. يسمح بالتحقق من أن نوع التعبير يفي بنوع معين، دون تغيير النوع المستنتج نفسه.

\n\n
// الطريقة القديمة: نفقد النوع الدقيق\nconst palette: Record<string, string | string[]> = {\n  red: [255, 0, 0],\n  green: "#00ff00",\n  blue: "#0000ff"\n};\n// palette.red — string | string[] (سيء)\n\n// الطريقة الجديدة مع satisfies\nconst palette = {\n  red: [255, 0, 0],\n  green: "#00ff00",\n  blue: "#0000ff"\n} satisfies Record<string, string | string[]>;\n\n// palette.red — number[] (تم الحفاظ على النوع الدقيق!)\n// palette.green — string\n// palette.blue — string

                
                

المدونات

توصيات الكتب