ValueOf في TypeScript: كيفية الحصول على نوع القيمة من الكائن

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

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

ابدأ الدورة

هل يوجد `valueof` مشابه لـ `keyof` في TypeScript؟ تحسين الأداء

\n\n

هل سبق لك أن كتبت كودًا بلغة TypeScript وتساءلت: «لدي keyof للمفاتيح، أين valueof للقيم؟» إذا كان الأمر كذلك، فأنت لست وحدك. هذا السؤال حصد آلاف المشاهدات على Stack Overflow، واليوم سنشرحه بالتفصيل. لكن ليس كنظرية مجردة، بل مع التركيز على تحسين الأداء وجودة الكود. هيا بنا!

\n\n

لماذا يوجد `keyof` ولا يوجد `valueof`؟

\n\n

في TypeScript، هناك نوع مساعد مدمج يُسمى keyof. يقوم هذا النوع بأخذ نوع كائن وإرجاع اتحاد جميع مفاتيحه:

\n\n
type Person = {\n  name: string;\n  age: number;\n  isActive: boolean;\n};\n\ntype PersonKeys = keyof Person; // "name" | "age" | "isActive"
\n\n

ماذا عن القيم؟ نرغب في الحصول على string | number | boolean من نفس النوع. لا يوجد مثل هذا النوع في المكتبة الأساسية لـ TypeScript. لماذا؟ لأن valueof ليست مجرد «عملية عكسية». يمكن أن يحتوي الكائن على العديد من المفاتيح ذات الأنواع المتطابقة، ونحتاج إلى تحديد كيفية دمجها. لكن هذا لا يعني أنه لا يمكننا كتابة valueof الخاص بنا!

\n\n

إنشاء `ValueOf` الخاص بك

\n\n

أسهل طريقة هي استخدام نوع الوصول المفهرس (indexed access type) مع keyof:

\n\n
type ValueOf<T> = T[keyof T];\n\ntype PersonValues = ValueOf<Person>; // string | number | boolean
\n\n

هذا كل شيء! لقد أنشأنا للتو نوعًا عامًا ValueOf يعمل مثل valueof. لكن دعنا نتعمق أكثر — كيف يؤثر هذا على الأداء وكيف نستخدمه بذكاء.

\n\n

تحسين الأداء: متى ينقذك `ValueOf` من التكرار

\n\n

تخيل أن لديك كائن تهيئة بعشرات الحقول. تريد كتابة دالة تقبل أي قيمة من هذا الكائن. بدون ValueOf، ستضطر إلى تعداد الأنواع يدويًا:

\n\n
type Config = {\n  apiUrl: string;\n  timeout: number;\n  retries: number;\n  debug: boolean;\n};\n\n// سيء: تكرار الأنواع\nfunction setConfigValue(key: string, value: string | number | boolean) {\n  // ...\n}
\n\n

الآن مع ValueOf:

\n\n
// جيد: يلتقط جميع أنواع القيم تلقائيًا\nfunction setConfigValue(key: keyof Config, value: ValueOf<Config>) {\n  // TypeScript يعلم أن القيمة يمكن أن تكون فقط string | number | boolean\n}
\n\n

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

\n\n

`ValueOf` متقدم مع الأنواع الشرطية

\n\n

أحيانًا تحتاج إلى الحصول على قيم مفاتيح معينة فقط. على سبيل المثال، جميع القيم الرقمية. هنا تأتي الأنواع الشرطية (conditional types) للإنقاذ:

\n\n
type NumericValues<T> = {\n  [K in keyof T]: T[K] extends number ? T[K] : never;\n}[keyof T];\n\ntype ConfigNumeric = NumericValues<Config>; // number (timeout | retries)
\n\n

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

\n\n

الأداء في وقت التشغيل: هل هو ضروري؟

\n\n

نقطة مهمة: ValueOf هو بناء نوعي بحت. لا ينتج أي كود JavaScript. لكن استخدامه الصحيح يمكن أن يعزز الأداء بشكل غير مباشر لتطبيقك:

\n\n
    \n
  • أخطاء أقل — وقت أقل في التصحيح.
  • \n
  • كتابة أكثر صرامة — المترجم يكتشف
  • \n

المدونات

توصيات الكتب