أطلق فريق TypeScript خيار مترجم (compiler flag) جديدًا في إصدار 6.0 وهو --noPropertyAccessFromIndexSignature. عند تفعيله، يرفض المترجم الوصول إلى الخصائص باستخدام "dot-notation" التي تأتي من "index signature"، مما يجبر المطورين على استخدام "bracket notation" وإظهار قيم undefined المحتملة في وقت التجميع بدلاً من وقت التشغيل.
لماذا يهم هذا الخيار
في JavaScript، غالبًا ما تعمل الكائنات كقواميس، ويسمح لك TypeScript بتحديد أنواع هذه الهياكل باستخدام "index signature"، مثل Record<string, T>. تتعامل اللغة مع obj.key و obj["key"] كأنهما قابلتان للتبادل، لذا يفترض المترجم وجود الخاصية حتى عندما لا تُعرف المفاتيح إلا في وقت التشغيل. هذا الافتراض الصامت هو مصدر العديد من الانهيارات: فالكود الذي يصل إلى obj.missingProp يتم تجميعه بنجاح، ويعمل، ثم يتوقف عن العمل (throws) لأن القيمة هي undefined.
تحمل "dot notation" ضمانًا ضمنيًا؛ فهي تخبر القراء وفاحص الأنواع (type checker) أن الخاصية موجودة بالتأكيد. في المقابل، تشير "bracket notation" إلى عدم اليقين - فقد يكون المفتاح مفقودًا، وقد تكون النتيجة undefined. يفرض --noPropertyAccessFromIndexSignature هذا التمييز البصري والدلالي، محولًا فئة من أخطاء وقت التشغيل إلى تشخيصات في وقت التجميع.
كيف يعمل الخيار
عند تفعيل الخيار، يتم وضع علامة خطأ على أي تعبير يصل إلى خاصية عبر "index signature" باستخدام "dot notation". يجب إعادة كتابة الكود لاستخدام الأقواس:
// Before
const name = userData.name; // OK even if "name" is not in the index
// After enabling the flag
const name = userData["name"]; // Error unless brackets are used
ثم يطبق المترجم نفس قواعد التعامل مع undefined التي يستخدمها بالفعل للوصول عبر الأقواس. إذا تم تفعيل --noUncheckedIndexedAccess أيضًا، يصبح نوع userData["name"] هو T | undefined مما يجبر المطور على التحقق من حالة فقدان القيمة.
خطوات الهجرة العملية
تفعيل الخيار في
tsconfig.json:{ "compilerOptions": { "noPropertyAccessFromIndexSignature": true } }تشغيل فاحص الأنواع (type checker). ستظهر جميع عمليات الوصول باستخدام "dot-notation" لمفاتيح "index-signature" كأخطاء.
استبدال النقاط بالأقواس. التغيير ميكانيكي؛ ولا يؤثر على أداء وقت التشغيل.
معالجة أنواع
undefinedالناتجة. أضف "nullish coalescing" أو "optional chaining" أو تحققات صريحة حيثما لزم الأمر.فكر في الجمع بينه وبين
--noUncheckedIndexedAccessللحصول على أقوى شبكة أمان. يضمنان معًا التعامل مع أي وصول بأسلوب القاموس على أنه قد يكون مفقودًا.
متى يجب الإبقاء على الخصائص الصريحة
إذا كان الحقل جزءًا من عقد API مستقر، فقم بتعريفه كخاصية صريحة بدلاً من الاعتماد على "index signature". تتيح الخصائص الصريحة الاستمرار في استخدام "dot notation"، مما يحافظ على الضمان بأن الحقل سيكون موجودًا دائمًا (بقدر ما يمكن لنظام الأنواع التحقق منه). احتفظ بـ "index signatures" للبيانات الديناميكية حقًا حيث لا تُعرف المفاتيح مسبقًا.
وجهة نظر مغايرة: زيادة الإطناب (verbosity)
قد تجد بعض الفرق أن الأقواس الإضافية تسبب "ضجيجًا" في الكود، خاصة في قواعد الأكواد التي تستخدم الكائنات المرنة بكثرة. يفرض هذا الخيار انضباطًا أكثر صرامة قد يتطلب إعادة هيكلة (refactor) كبيرة للمشاريع القديمة. في هذه الحالات، يمكن إدخال الخيار تدريجيًا، ربما قصرًا على الوحدات (modules) الجديدة، بينما تتبنى قاعدة الكود الأوسع هذا النمط بمرور الوقت.
ما يجب مراقبته لاحقًا
يعد هذا الخيار جزءًا من توجه أوسع في TypeScript 6.0 نحو سلامة أنواع (type safety) أكثر صرامة. قد تقدم الإصدارات المستقبلية فحوصات إضافية حول "object spread" أو "optional chaining" أو استخدام any المستنتج. إن مراقبة خارطة طريق TypeScript ستساعد الفرق على تحديد موعد اعتماد المجموعة التالية من ميزات الأمان دون تعطيل جداول التسليم.
الخلاصة: إن تفعيل --noPropertyAccessFromIndexSignature يجعل التمييز بين "هذه الخاصية مضمونة" و "هذه الخاصية قد تكون مفقودة" صريحًا في الكود، مما يكشف عن فئة كاملة من الأخطاء قبل وصولها إلى بيئة الإنتاج. تحويل فشل وقت التشغيل الصامت إلى خطأ في وقت التجميع هو تغيير صغير له تأثير هائل على الموثوقية.
