Record في TypeScript: ما هو وكيف تستخدمه للمبتدئين

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

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

ابدأ الدورة

Record في TypeScript: فهم عملي

\n\n

تخيل أنك تكتب تطبيقًا لتعلم الكلمات الإنجليزية. تحتاج إلى تخزين الترجمات: cat → قطة، dog → كلب. كيف تكتب الأنواع (types) بشكل صحيح في TypeScript؟ يمكنك إنشاء واجهة (interface)، لكن ماذا لو كانت المفاتيح غير معروفة مسبقًا؟ أو كان عددها كبيرًا جدًا؟ هنا يأتي دور Record — أحد أكثر أنواع الأدوات (utility types) فائدةً، لكنه غالبًا ما يُقلل من شأنه.

\n\n

في هذه المقالة، سنشرح ما هو Record type في TypeScript، مع أمثلة واقعية يمكنك تطبيقها فورًا في مشاريعك. لا نظرية مملة — فقط تطبيق عملي.

\n\n

ما هو Record في TypeScript؟ شرح بسيط

\n\n

Record<K, V> هو نوع أداة (utility type) مدمج ينشئ كائنًا حيث جميع المفاتيح من النوع K وجميع القيم من النوع V.
فكر فيه كـ قاموس مكتوب (typed dictionary) أو خريطة (map) بمجموعة محددة من المفاتيح.

\n\n

الصيغة الأساسية تبدو كالتالي:

\n\n
// كائن عادي\nconst userRoles: Record<string, string> = {\n  admin: 'مدير',\n  user: 'مستخدم',\n  guest: 'ضيف'\n};
\n\n

هنا Record<string, string> تعني: "كائن حيث المفاتيح نصوص والقيم نصوص أيضًا". بسيط وواضح.

\n\n

لماذا Record أفضل من الواجهة (interface) العادية؟

\n\n
    \n
  • مرونة المفاتيح: يمكنك تحديد مجموعة محددة من المفاتيح باستخدام union type.
  • \n
  • الإيجاز: لا حاجة لوصف كل حقل يدويًا.
  • \n
  • الأمان: سيتحقق TypeScript من أنك تستخدم فقط المفاتيح المسموح بها.
  • \n
\n\n

Record مقابل الكائن العادي: مثال توضيحي

\n\n

لنفترض أن لدينا حالات الطلب: pending، shipped، delivered. بدون Record، ستحتاج إلى كتابة واجهة بثلاثة حقول:

\n\n
interface OrderStatusMap {\n  pending: string;\n  shipped: string;\n  delivered: string;\n}\n\nconst statusDescriptions: OrderStatusMap = {\n  pending: 'قيد الانتظار',\n  shipped: 'تم الشحن',\n  delivered: 'تم التوصيل'\n};
\n\n

أما مع Record — فهو أكثر إيجازًا ووضوحًا:

\n\n
type OrderStatus = 'pending' | 'shipped' | 'delivered';\n\nconst statusDescriptions: Record<OrderStatus, string> = {\n  pending: 'قيد الانتظار',\n  shipped: 'تم الشحن',\n  delivered: 'تم التوصيل'\n};
\n\n

الميزة: إذا حاولت إضافة cancelled إلى الكائن، سيشير TypeScript فورًا إلى الخطأ — هذه الحالة غير موجودة في union type.

\n\n

أفضل 5 أمثلة عملية لاستخدام Record

\n\n

لنرَ أين يُبسّط Record حياتنا حقًا.

\n\n

1. إعدادات التطبيق

\n

خزّن الإعدادات بمفاتيح معروفة ولكن بقيم مختلفة الأنواع:

\n\n
type ConfigKeys = 'apiUrl' | 'timeout' | 'retryCount';\ntype ConfigValue = string | number | boolean;\n\nconst appConfig: Record<ConfigKeys, ConfigValue> = {\n  apiUrl: 'https://api.example.com',\n  timeout: 5000,\n  retryCount: 3\n};
\n\n

2. ربط التعدادات (enums) أو الثوابت

\n

غالبًا ما تحتاج إلى ربط كود باسم قابل للقراءة البشرية:

\n\n
enum HttpStatus {\n  OK = 200,\n  NotFound = 404,\n  Error = 500\n}\n\nconst statusMessages: Record<HttpStatus, string> = {\n  [HttpStatus.OK]: 'كل شيء بخير',\n  [HttpStatus.NotFound]: 'غير موجود',\n  [HttpStatus.Error]: 'خطأ في الخادم'\n};
\n\n

3. النماذج والتحقق من الصحة

\n

Record مثالي لتخزين أخطاء التحقق حسب الحقول:

\n\n
type FormFields = 'email' | 'password' | 'name';\ntype ValidationErrors = Record<FormFields, string | null>;\n\nconst errors: ValidationErrors = {\n  email: 'بريد إلكتروني غير صالح',\n  password: null,\n  name: 'الاسم مطلوب'\n};
\n\n

4. تخزين مؤقت للبيانات (Cache)

\n

محاكاة ذاكرة تخزين مؤقت بمفاتيح معرفة:

\n\n
type UserI                

المدونات

توصيات الكتب