العودة إلى المدونة

لغات البرمجة21 أكتوبر 20254 دقائق قراءة

انتصرت TypeScript... وهذه فاتورة الانتصار

أسامـــة الدروشـــي

حاسوب محمول يعرض شيفرة TypeScript ملوّنة وبجانبه صبّار صغير

أستطيع أن أحدد اللحظة التي أدركت فيها أن TypeScript انتصرت. لم تكن في استبيان ولا في كلمة افتتاحية بمؤتمر؛ بل حين فتح مطوّر مبتدئ ملفَّ أدوات قديمًا في المشروع وسألني بحيرة صادقة: لماذا هذا الملف «بلا أنواع»؟ لم يسأل لماذا اختار أحدهم JavaScript لكتابته، بل سأل وكأن الملف معطوب. في مكان ما على الطريق، توقفت JavaScript الصِّرفة عن كونها خيارًا وصارت عيبًا يجب إصلاحه.

لم يصوّت أحد، لكن الجميع امتثل

حسمت Angular هذا السؤال عني طوال نصف مسيرتي دون أن تستشيرني. كل مشاريع Angular التي قدتها، من منصة «صبر» التحليلية التي بنيناها لهيئة تنظيم الاتصالات في عُمان، إلى نظام «المؤشرات» الذي تقدّم عبره شركات الاتصالات تقاريرها التنظيمية، كانت TypeScript منذ أول commit، لأن Angular ببساطة لا تفتح بابًا آخر. ساحة المعركة الحقيقية كانت React، وهناك شاهدت الحرب تنتهي. حين بدأت العمل الحر عام 2020، كان أي مشروع React جديد يمر بطقس صغير: أحدهم يقترح TypeScript، وآخر يقول إنها تبطئ الفريق، ثم يُعقد حل وسط ويُحوَّل نصف الملفات. وحين صرت أقود التطوير في Sagan World بعد سنوات قليلة، كان الطقس قد اختفى تمامًا: مشروع React جديد يعني ملفات tsx وstrict: true، والسؤال التالي من فضلك. لم يصوّت أحد؛ الافتراضي انقلب تحت أقدامنا وحسب.

ما الذي كسبناه فعلًا؟

أريد أن أكون دقيقًا هنا، لأن المكاسب حقيقية ومحددة، لا مجرد انطباعات.

أكبرها الثقة عند إعادة الهيكلة. في منصة تحليلات M2M التي بنيناها لـ Ooredoo كنا نتابع بيانات نحو 300 ألف جهاز مزوّد بشرائح SIM، وكان شكل تلك البيانات يتغير باستمرار كلما طرح العمل أسئلة جديدة. أن تعيد تسمية حقل في نوع استجابة أساسي ثم يقودك المترجم إلى أربعين موضع استدعاء مكسورًا واحدًا تلو الآخر، تجربة مختلفة جذريًا عن البحث النصي والدعاء. جرّبت الاثنتين، ولن أعود.

الثاني هو العقود بين الفرق. حين تكون الواجهة الخلفية Spring Boot أو FastAPI والواجهة الأمامية فريقًا آخر في مستودع آخر، فإن مجموعة الأنواع المشتركة هي أرخص توثيق لـ API عرفته هذه الصناعة، لأنها التوثيق الوحيد الذي يُفشل البناء حين يكذب.

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

الضريبة التي ندفعها بصمت

وهذا ما لا نضعه في عروض المؤتمرات.

  • بهلوانيات الأنواع. راجعت طلبات دمج استغرق فهم النوع الشرطي المعمّم فيها وقتًا أطول من فهم الدالة التي يصفها. كان يُفترض بالأنواع أن تصف الشيفرة؛ وفي لحظة ما صرنا نكتب شيفرة لإرضاء الأنواع.
  • تعقيد البناء. كل مشروع TypeScript يحمل برنامجًا ثانيًا: البرنامج الذي يحوّل شيفرتك إلى شيفرة. خيارات tsconfig، وts-node مقابل tsx مقابل esbuild، وأنماط حلّ الوحدات بأسماء تشبه التعاويذ. حين ينكسر البناء، فأنت تصحح سلسلة أدوات، لا منتجك.
  • اقتصاد any. صرامة على الورق، ومخارج طوارئ في الممارسة. عبارة as unknown as User كذبة بخطوات إضافية، وتظهر بالضبط حيث تكون الشيفرة في أخطر حالاتها: عند الحدود، حيث تأتي البيانات فعلًا من الخارج.
  • جيل يخاف JavaScript. هذا ما يقلقني أكثر من غيره. قابلت مطوّرين يكتبون أنواعًا معمّمة أنيقة ثم يتجمّدون حين أسألهم عمّا يحدث وقت التشغيل، لأن النوع في أذهانهم هو الضمانة ذاتها. وهو ليس كذلك؛ الأنواع تُمحى قبل أن تعمل شيفرتك أصلًا، وما يزال بإمكان الـ API أن يرسل لك null في الثانية فجرًا، وسيفعل.
النوع وعدٌ تقطعه لنفسك؛ الشبكة لم توقّع عليه قط.

كيف نتعايش مع المنتصر؟

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

أبقوا أنواع التطبيق مملة؛ فإن احتاج نوعٌ إلى تدوينة كاملة ليُفهم، فمكانه مكتبةٌ لا شيفرة الميزات. تحققوا من البيانات عند الحدود بشيء يعمل وقت التشغيل، لأن ثقة المترجم تنتهي حيث تبدأ الشبكة. واكتبوا بين حين وآخر سكربتًا صغيرًا بـ JavaScript صِرفة، فقط لتتذكروا أن اللغة تحت السطح ما تزال هناك، وما تزال بخير، وما تزال هي ما يُنفَّذ فعلًا.

انتصرت TypeScript، وهذا هو الخبر السار. أما الكلفة فلا تصبح مشكلة إلا حين نصرّ على إنكار وجودها.