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

صممت الجافاسكربت أصلاً كلغة برمجة بسيطة. طبيعتها الفضفاضة وغياب ميزات البرمجة الشيئية الحيوية تثير تحديات معينة للمطورين:

  1. الوثائق المحدودة وعدم الاكتمال التلقائي.

  2. عدم القدرة على استخدام مفاهيم البرمجة الشيئية.

  3. نقص في سلامة النوع، مما يؤدي إلى أخطاء في وقت التشغيل.

  4. تحديات في إعادة التصميم والصيانة.

  5. غياب الواجهات ونقاط التكامل.

يحل TypeScript هذه المشاكل. تم بناؤها لجعل الجافاسكربت لغة برمجة حديثة أكثر اكتمالًا. يساعد في تحسين تجربة المطور، ويقدم العديد من الميزات المفيدة، ويحسن التوافق.

يستعرض هذا المقال أساسيات TypeScript. سأعلمك كيفية تثبيت TypeScript وإعداد مشروع. ثم سنغطي بعض الأساسيات الهامة. ستتعلم أيضًا كيف يترجم TypeScript إلى جافاسكربت، مما يجعله متوافقًا مع متصفحات الويب وبيئات Node.js.

ما سنغطيه:

المتطلبات الأساسية

قبل الغوص في TypeScript، من المهم أن يكون لديك فهم أساسي لبعض المفاهيم لضمان رحلة تعلم أكثر سلاسة. بينما يعزز TypeScript لغة JavaScript مع الأنواع الثابتة وميزات قوية أخرى، فإنه يبني على مبادئ JavaScript الأساسية. إليك ما يجب أن تعرفه:

1. أساسيات JavaScript

TypeScript هو مجموعة فوقية من JavaScript، مما يعني أنه يوسع قدرات JavaScript. لتتعلم TypeScript بشكل فعال، يجب أن يكون لديك أولاً فهم قوي لأساسيات JavaScript، بما في ذلك:

  • البناء والتركيبات البيانية: فهم كيفية إعلان المتغيرات (let، const، وvar)، والعمل مع الأنواع البدائية (السلاسل النصية، الأعداد، القيم المنطقية)، وإدارة المصفوفات والكائنات.

  • تدفق التحكم: كن على دراية بالحلقات (for، while)، والشروط (if-else، switch)، وكيف تتحكم في تنفيذ البرنامج.

  • الدوال: تعرف على كيفية تعريف الدوال واستدعائها، والعمل مع المعاملات وقيم الإرجاع، وفهم مفاهيم مثل الدوال السهمية والإغلاقات.

  • البرمجة الشيئية (OOP): تعلم كيفية إنشاء الكائنات والعمل معها ومع الصفوف والوراثة. تعتمد ميزات TypeScript المعتمدة على الصفوف بشكل كبير على نموذج البرمجة الشيئية في JavaScript.

  • معالجة الأخطاء: فهم كيفية استخدام كتل try-catch للتعامل مع الأخطاء أثناء التشغيل.

2. HTML و CSS الأساسيين

على الرغم من أن TypeScript هو لغة تستخدم أساسًا مع JavaScript، إلا أن فهمًا أساسيًا لـ HTML و CSS مفيد، خاصة بالنسبة لمطوري الواجهة الأمامية. وذلك لأن معظم مشاريع TypeScript تتضمن إنشاء أو العمل مع تطبيقات الويب

  • HTML: فهم كيفية بناء صفحات الويب باستخدام العلامات والسمات والعناصر.

  • CSS: تعلم كيفية تنسيق العناصر باستخدام المحددات والخصائص والقيم. إلمام بأطر عمل CSS مثل Bootstrap يعتبر ميزة إضافية.

3. إلمام بأدوات التطوير

  • محرر الأكواد مثل Visual Studio Code، الذي يوفر دعمًا ممتازًا لـ TypeScript وامتدادات.

  • Node.js و npm: فهم كيفية إعداد بيئة تطوير، تشغيل JavaScript خارج المتصفح، واستخدام npm (Node Package Manager) لتثبيت التبعيات.

  • نظام التحكم بالنسخ (Git): تعلم أساسيات Git لتتبع التغييرات والتعاون بفعالية في مشاريع TypeScript.

البدء – كيفية تثبيت TypeScript

للبدء في العمل مع TypeScript، ستحتاج إلى تثبيته. إنها ليست عملية معقدة. مع تثبيت TypeScript، يمكنك الاستفادة من قوته لإنشاء حلول عالية الجودة.

يمكنك تثبيت TypeScript بطريقتين:

  1. التثبيت العالمي: يتيح لك الوصول إلى المجمع من أي دليل على جهازك. لتثبيت TypeScript عالميًا، نفذ الأمر التالي:
npm install -g typescript

هذا الأمر يستخدم مدير حزم Node.js، npm. يقوم بتثبيت TypeScript عالميًا، مما يجعل الأمر متاحًا في سطر الأوامر.

  1. التثبيت المحلي: في هذه الحالة، يتم تثبيت TypeScript فقط ضمن مشروع معين. تضمن هذه الطريقة توافق النسخ والاتساق بين أعضاء الفريق. لتثبيت TypeScript محليًا، نفذ الأمر التالي:
npm install typescript --save-dev

مختلف عن التثبيت العالمي، يقوم هذا الأمر بتثبيت TypeScript كاعتماد تطوير. أمر tsc متاح فقط للاستخدام الخاص بالمشروع، أي المشروع المحدد الذي تقوم بتشغيل الأمر فيه.

هل يمكنك تثبيت TypeScript بسلاسة الآن؟ آمل ذلك!

كيفية تنظيم مشاريع TypeScript الخاصة بك

تنظيم مشروع TypeScript يتضمن هيكلة ملفاتها بأسماء ودلائل ذات معنى، وفصل الاهتمامات، واستخدام الوحدات للتغليف وإعادة الاستخدام.

الامتداد .ts يدل على ملفات TypeScript ويحتوي على كود يتم تحويله إلى JavaScript للتنفيذ.

يدعم TypeScript أيضًا ملفات .d.ts، المعروفة أيضًا بملفات تعريف الأنواع. تقدم هذه الملفات معلومات عن الأنواع بشأن مكتبات JavaScript الخارجية أو الوحدات، مما يساعد في التحقق من الأنواع بشكل أفضل واكتمال الشيفرة، ويعزز كفاءة التطوير. فيما يلي مثال على هيكل مشروع TypeScript جيد:

my-ts-project/
├── src/ 
│   ├── components/ 
│   │   ├── Button.tsx
│   │   ├── Input.tsx
│   │   └── Modal.tsx
│   ├── services/ 
│   │   ├── api.ts
│   │   └── authService.ts
│   ├── utils/ 
│   │   ├── helpers.ts 
│   │   └── validators.ts
│   ├── models/ 
│   │   ├── User.ts
│   │   └── Product.ts
│   ├── index.tsx 
│   └── styles/ 
│       ├── global.css
│       └── theme.css
├── public/ 
│   ├── index.html
│   └── assets/ 
│       ├── images/
│       └── fonts/
├── tsconfig.json
└── package.json

دعونا نفهم ما يحدث هنا:

  1. src/: هذا الدليل يحتوي على جميع شفرات المصدر للمشروع.

    • components/: يحتوي على مكونات واجهة المستخدم قابلة لإعادة الاستخدام (على سبيل المثال، Button، Input، Modal). استخدام .tsx (TypeScript JSX) يسمح لك بكتابة JSX بأمان الأنواع.

    • services/: يحتوي على خدمات تتفاعل مع واجهات برمجة التطبيقات الخارجية أو تدير منطق التطبيق (على سبيل المثال، api.ts لاستدعاء واجهات برمجة التطبيقات، authService.ts للمصادقة).

    • utils/: يحتوي على وظائف مساعدة وفئات أدوات للمهام الشائعة (على سبيل المثال، helpers.ts لتنسيق التواريخ، validators.ts للتحقق من الإدخال).

    • models/: يحدد واجهات TypeScript أو فئات لتمثيل هياكل البيانات (على سبيل المثال، User.ts، Product.ts).

    • index.tsx: نقطة الدخول الرئيسية للتطبيق.

    • styles/: يحتوي على ملفات CSS أو تنسيقات أخرى.

  2. public/: هذا الدليل يحتوي على الأصول الثابتة التي لا تتم معالجتها بواسطة TypeScript (على سبيل المثال، HTML، صور، خطوط).

  3. tsconfig.json: ملف تكوين TypeScript، يحدد خيارات المترجم.

  4. package.json: ملف تعريف المشروع، يسرد التبعيات، النصوص، وبيانات المشروع الأخرى.

مجرد ملاحظة سريعة حول تعليمات التسمية لكي تفهمها هنا:

  • استخدم PascalCase لأسماء الفئات (على سبيل المثال، User، Product).

  • استخدم camelCase لأسماء الدوال والمتغيرات (على سبيل المثال، getUser، firstName).

  • استخدم أسماء ذات معنى ووصفية للملفات والمجلدات.

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

تنظيم مشاريعك في TS بشكل صحيح يعزز من قابلية صيانة الكود، وقابلية القراءة، والتعاون في سير عمل تطوير TypeScript.

كيف يعمل النمط في TypeScript

مثل أي لغة برمجة ذات نوع ثابت أخرى، تعتمد TypeScript على تعريفات الأنواع، والتي تُعرف عمومًا باسم النمط.

النمط هو مصطلح يُستخدم في البرمجة لتحديد أنواع البيانات للمتغيرات، ومعلمات الدوال، والقيم العائدة ضمن الكود.

يسمح لك النمط باكتشاف الأخطاء بسرعة وفي وقت مبكر من التطوير، وهي قوة عظيمة تساعد في الحفاظ على جودة الكود بشكل أفضل.

لتحديد نوع في TypeScript، ضع نقطتين( :) ونوع البيانات المرغوب بعد اسم المتغير الخاص بك. إليك مثال:

let age: number = 2;

تم إعلان المتغير أعلاه بنوع number. في TypeScript، يعني هذا أنه يمكنه تخزين الأرقام فقط وليس شيئًا آخر.

تقنيات النمط

في TypeScript، يمكن أن تُحدد البيانات بنوعين رئيسيين:

  1. النمط الثابت: يشير النمط الثابت إلى تحديد نوع البيانات للمتغيرات والكيانات الأخرى في الكود بشكل صريح أثناء التطوير. يفرض مترجم TypeScript هذه التعريفات النوعية، مما يساعد على اكتشاف الأخطاء المتعلقة بالنمط مبكرًا. على سبيل المثال:
let age: number = 25;

هنا، يتم إعلان المتغير age بشكل صريح ليكون من نوع number. وهذا يضمن أنه يمكن فقط تعيين القيم الرقمية له، مما يقلل من خطر حدوث أخطاء في وقت التشغيل.

  1. الكتابة الديناميكية: تشير الكتابة الديناميكية في TypeScript إلى السيناريوهات التي يتم فيها تحديد نوع المتغير في وقت التشغيل. يمكن أن يحدث ذلك عندما يتم تعيين المتغيرات لنوع any، مما يسمح لها بحمل قيم من أي نوع. لا يقوم TypeScript بإجراء فحص نوع العمليات التي تتضمن متغيرات من نوع any.
let value: any;
value = 25; // عدد
value = "Hello"; // سلسلة

بينما يُعتبر TypeScript لغة مكتوبة بشكل أساسي، يمكن أن تكون الكتابة الديناميكية مفيدة في حالات معينة، مثل:

  • العمل مع مكتبات الطرف الثالث التي تفتقر إلى تعريفات الأنواع.

  • التفاعل مع بيانات مهيكلة ديناميكيًا (على سبيل المثال، استجابات JSON من واجهات برمجة التطبيقات ذات الهياكل غير المعروفة).

  • النمذجة السريعة أو عندما تكون معلومات النوع غير متاحة خلال مرحلة التطوير الأولية.

الكتابة الثابتة مقابل الكتابة الديناميكية في TypeScript

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

عادةً ما يتم تخصيص النوع الديناميكي للحالات التي تتطلب مرونة أو عند التعامل مع بيانات لا يمكن تحديد هيكلها مسبقًا. فقط تذكر أن الاعتماد بشكل كبير على النوع الديناميكي (على سبيل المثال، الإفراط في استخدام النوع any) يتم تجنبه عمومًا، حيث إنه يقوض فوائد نظام النوع الثابت في TypeScript.

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

استدلال النوع وأنواع الاتحاد

استدلال النوع

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

على سبيل المثال:

typescriptCopyEditlet age = 25; // يستنتج TypeScript أن 'age' من نوع 'number'
age = "hello"; // خطأ: النوع 'string' لا يمكن تعيينه إلى النوع 'number'

في هذا المثال، يتم استنتاج متغير age تلقائيًا كـ number بسبب قيمته الأولية، 25. أي محاولة لإعادة تعيين age إلى قيمة من نوع مختلف (مثل سلسلة نصية) ستؤدي إلى حدوث خطأ في النوع.

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

متى تستخدم استنتاج النوع:
  • التعيينات البسيطة: استخدم استنتاج النوع للتعيينات البسيطة حيث يكون النوع واضحًا من القيمة.

  • القيم الافتراضية: عند توفير قيم افتراضية للمتغيرات أو معلمات الدالة، يضمن استنتاج النوع تطبيق النوع الصحيح دون الحاجة إلى تعليقات يدوية.

  • النماذج الأولية السريعة: خلال المراحل المبكرة من التطوير، يمكن أن يقلل استنتاج النوع من الشيفرات الزائدة بينما لا يزال يفرض أمان النوع.

أنواع الاتحاد

تسمح أنواع الاتحاد لمتغير بأن يحمل قيم من أنواع متعددة. يتم تعريفها عن طريق وضع خط أنبوب (|) بين الأنواع. هذه الميزة مفيدة بشكل خاص عندما يمكن لمتغير أن يحمل بشكل شرعي أكثر من نوع واحد خلال دورته الحياة.

على سبيل المثال:

typescriptCopyEditlet numOrString: number | string; // 'numOrString' يمكن أن يحمل إما رقمًا أو سلسلة نصية
numOrString = 25; // صحيح
numOrString = "hello"; // صحيح
numOrString = true; // خطأ: النوع 'boolean' لا يمكن تعيينه إلى النوع 'number | string'

يمكنك حتى تعريف أنواع الاتحاد بأكثر من نوعين ممكنين:

typescriptCopyEditlet multiType: number | string | boolean;
multiType = 42; // صحيح
multiType = "TypeScript"; // صحيح
multiType = false; // صحيح
متى يجب استخدام أنواع الاتحاد:
  • معلمات دالة مرنة: عندما يمكن لدالة قبول أنواع متعددة من المدخلات.

      typescriptCopyEditfunction printValue(value: string | number) {
        console.log(value);
      }
    
  • معالجة هياكل البيانات المتنوعة: عند العمل مع واجهات برمجة التطبيقات أو مصادر البيانات الخارجية حيث قد تختلف الحقول في النوع.

  • المتغيرات الاختيارية أو متعددة الحالات: على سبيل المثال، متغير يمكن أن يمثل حالة تحميل كقيمة Boolean، أو خطأ كسلسلة نصية، أو بيانات صالحة ككائن:

      typescriptCopyEditlet status: boolean | string | { success: boolean; data: any };
    

كيفية التعامل مع الكائنات، والمصفوفات، وأنواع الدوال في TypeScript

لإتقان TypeScript، يجب أن تفهم أنواع البيانات المختلفة المدعومة في TypeScript وكيف ومتى تستخدمها.

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

أنواع الكائنات في TypeScript

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

لتعريف نوع كائن، حدد بوضوح مخطط الكائن بعد النقطتين (:). على سبيل المثال:

// تهيئة نوع الكائن

let student: {
    name: string;
    age: number;
    matricNumber: string | number;
 };

// تعيين الكائن بالبيانات الفعلية

student = {
    name: "Akande"
    age: 21,
    matricNumber: 21/52 + "HP" + 19,
};

لاحظ أن الخصائص تنتهي بفاصلة منقوطة ; بدلاً من فاصلة , التي تنهيها في كائن فعلي.

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

أنواع المصفوفات في TypeScript

تسمح الأرَرايـات في TypeScript بتخزين قيم متعددة من نفس النوع أو أنواع بيانات مختلفة في متغير واحد. تعزز الأرَرايـات سلامة ووضوح الشفرة الخاصة بك من خلال فرض توافق الأنواع عبر عناصر الأرَرايـات.

في TypeScript، يمكن تعريف أنواع الأرَرايـات بطريقتين:

1. باستخدام النموذج Array<type>

تستخدم هذه الصيغة نوع Array العام، حيث يمثل type نوع العناصر التي يمكن أن تحتويها الأرَرايـة.

typescriptCopyEditlet numbers: Array<number> = [1, 2, 3, 4, 5];
let mixedArray: Array<number | string> = [1, 2, 3, 4, 5, "Hello"];
  • numbers مثال: يمكن أن تحتوي هذه الأرَرايـة فقط على أرقام. محاولة إضافة سلسلة نصية أو نوع آخر إلى هذه الأرَرايـة ستؤدي إلى خطأ في النوع.

      typescriptCopyEditnumbers.push(6); // صحيح
      numbers.push("مرحبًا"); // خطأ: النوع 'string' لا يمكن تعيينه إلى النوع 'number'
    
  • mixedArray مثال: تستخدم هذه المصفوفة نوع اتحاد (number | string)، مما يسمح بتخزين كل من الأرقام والسلاسل.

      typescriptCopyEditmixedArray.push(42); // صالح
      mixedArray.push("TypeScript"); // صالح
      mixedArray.push(true); // خطأ: نوع 'boolean' لا يمكن تعيينه إلى نوع 'number | string'
    

2. استخدام نموذج type[]

تضيف هذه الصيغة أقواس مربعة ([]) إلى نوع العناصر التي يمكن أن يحتوي عليها المصفوفة.

typescriptCopyEditconst numbers: number[] = [1, 2, 3, 4, 5];
const mixedArray: (string | number)[] = [1, 2, 3, 4, 5, "Hello"];
  • numbers مثال: مشابه لمثال Array<number>، هذه المصفوفة يمكنها فقط احتواء الأرقام.

      typescriptCopyEditnumbers[0] = 10; // صالح
      numbers.push("مرحباً"); // خطأ: النوع 'string' لا يمكن تعيينه إلى النوع 'number'
    
  • mixedArray مثال: مثل mixedArray السابق، تسمح هذه المصفوفة بكل من الأرقام والسلاسل النصية، مما يوفر مرونة حيث قد يختلف نوع البيانات.

      typescriptCopyEditmixedArray[1] = "العالم"; // صحيح
      mixedArray.push(true); // خطأ: النوع 'boolean' غير قابل للتعيين إلى النوع 'string | number'
    

كيفية استخدام المصفوفات في TypeScript

المصفوفات متعددة الاستخدامات وتستخدم عادةً لتخزين مجموعات من البيانات ذات الصلة. إليك بعض السيناريوهات العملية:

تخزين البيانات المتجانسة:
عندما تشترك جميع العناصر في المصفوفة في نفس النوع، مثل قائمة معرفات المستخدمين أو أسعار المنتجات:

typescriptCopyEditconst userIds: number[] = [101, 102, 103];
const productPrices: Array<number> = [29.99, 49.99, 19.99];

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

typescriptCopyEditconst messages: (string | object)[] = [
  "Welcome",
  { type: "error", text: "Something went wrong" },
];

التكرار على المصفوفات:
يمكن استخدام المصفوفات في TypeScript في الحلقات مع أمان نوع كامل:

typescriptCopyEditconst scores: number[] = [80, 90, 70];
scores.forEach((score) => console.log(score + 5)); // يضيف 5 لكل درجة

معلمات الدالة وأنواع القيم المرتجعة:
يمكن أيضًا تمرير المصفوفات كمعلمات للدالة أو إرجاعها بواسطة الدوال مع تحديد صارم للنوع:

typescriptCopyEditfunction getNumbers(): number[] {
  return [1, 2, 3];
}
function printStrings(strings: string[]): void {
  strings.forEach((str) => console.log(str));
}

أنواع الدوال في TypeScript

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

function addition (a: number, b: number): number {
return a + b;
}

تأخذ الدالة أعلاه عددين، تجمعهما، وتعيد عددًا. لن تعمل الدالة إذا كان أي من معلماتها ليس عددًا وإذا أعادت أي شيء آخر غير عدد. على سبيل المثال:

  1. استدعاء الدالة مع سلسلة كنمط:
// لن تعمل هذه لأن الدالة تتوقع أعدادًا، وأحد المعلمات هو سلسلة

addition(1, "two");
  1. إعادة كتابة الدالة لإرجاع سلسلة:
// ستعيد الدالة خطأ لأنها تعيد سلسلة

function addition (a: number, b: number): string {
    let result = a + b;
    let returnStatement = `Addition of ${a} and ${b} is: ${result}`;
    return returnStatement;
}

اختبر الكود بنفسك لترى كيف تعمل هذه الأمثلة.

فهم والتعامل بفعالية مع الكائنات، والمصفوفات، والدوال في TypeScript يمكنك من كتابة كود آمن من ناحية الأنواع وسهل الصيانة، مما يعزز من موثوقية وقابلية توسع تطبيقاتك.

كيفية إنشاء أنواع مخصصة في TypeScript

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

تسمح الأنواع المخصصة لك بتعريف هيكل البيانات الخاص بك والأشكال وفقًا لاحتياجاتك. وهذا يعزز قراءة الكود وسهولة الصيانة.

كلمة المفتاح Type

كلمة type تتيح لك إنشاء اختصارات أنواع، وتوفر وسيلة لإنشاء أنواع مخصصة. يمكن إعادة استخدام الأنواع التي تنشئها في جميع أنحاء قاعدة الكود الخاصة بك. تساعد اختصارات الأنواع في تعريف أنواع الاتحاد أو دمج الأنواع في اختصارات واحدة. بنية الجملة لإنشاء نوع مخصص هي كما يلي:

// بنية الجملة

type TypeAlias = type;

وإليك مثال:

الكود أعلاه ينشئ نوعًا مخصصًا UserName، اتحادًا بين الأرقام والسلاسل. يستخدم النوع الذي تم إنشاؤه لتعريف متغيرين بشكل نسبي للتحقق مما إذا كان النوع يعمل.

يرجى ملاحظة أنه من المستحسن أن يبدأ اسم النوع بحرف كبير.

كلمة المفتاح Type عادة ما تستخدم للأنواع الأساسية – ولكن ماذا عن إنشاء نوع مخصص للكائن؟

هنا تأتي الواجهات.

واجهات TypeScript

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

تعريف واجهة

يتم تعريف الواجهة باستخدام الكلمة الرئيسية interface. تبدو البنية النحوية كالتالي:

typescriptCopyEditinterface InterfaceName {
  property1: Type;
  property2: Type;
}

مثال:

typescriptCopyEditinterface User {
  id: number;
  name: string;
  email: string;
}

const user: User = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
};

إليك ما يحدث في هذا المثال:

  1. إعلان واجهة (interface User):

    • هنا، نحدد خطة لكائن User. تحدد أنه يجب أن يحتوي أي كائن من نوع User على الخصائص التالية:

      • id من نوع number

      • name من نوع string

      • email من نوع string

  2. باستخدام الواجهة (const user: User):

    • نقوم بإعلان كائن user من نوع User.

    • من المطلوب أن يحتوي الكائن على جميع الخصائص المحددة في واجهة User، مع قيم من الأنواع المحددة. إذا كانت خاصية مفقودة أو لم تتطابق نوعها، سيقوم TypeScript بإلقاء خطأ في وقت التجميع.

على سبيل المثال:

    typescriptCopyEditconst invalidUser: User = {
      id: 1,
      name: "Alice",
      // خطأ: الخاصية 'البريد الإلكتروني' مفقودة في النوع
    };

لذا قد تتساءل – لماذا يجب عليك استخدام الواجهات؟

  • سلامة النوع: تضمن أن الكائنات تتوافق مع الهيكل المتوقع، مما يمنع الأخطاء أثناء التشغيل.

  • قابلية إعادة الاستخدام: يمكن إعادة استخدام نفس الواجهة عبر أجزاء مختلفة من التطبيق، مما يقلل من التكرار.

  • وضوح الشفرة: يجعل الشفرة أسهل قراءة وفهمًا عن طريق وصف شكل الكائنات بشكل صريح.

الميزات المتقدمة للواجهات

  1. الخصائص الاختيارية: يمكنك جعل الخصائص اختيارية عن طريق إضافة علامة الاستفهام (؟).

     typescriptCopyEditinterface المنتج {
       id: number;
       name: string;
       description?: string; // الخاصية الاختيارية
     }
    
     const المنتج: المنتج = {
       id: 101,
       name: "الكمبيوتر المحمول",
     }; // صالح، حيث أن 'description' اختياري
    
  2. خصائص القراءة فقط: استخدم readonly لمنع الخصائص من التعديل بعد التهيئة.

     typescriptCopyEditinterface Point {
       readonly x: number;
       readonly y: number;
     }
    
     const point: Point = { x: 10, y: 20 };
     point.x = 15; // خطأ: لا يمكن تعيين 'x' لأنه خاصية قراءة فقط
    
  3. تمديد الواجهات: يمكن للواجهات أن ترث الخصائص من واجهات أخرى، مما يمكن التكوين.

     typescriptCopyEditinterface شخص {
       اسم: string;
       عمر: number;
     }
    
     interface موظف extends شخص {
       رقم_الموظف: number;
     }
    
     const موظف: موظف = {
       اسم: "جون",
       عمر: 30,
       رقم_الموظف: 1234,
     };
    

متى يجب استخدام الواجهات

هناك سيناريوهات مختلفة يكون من الجيد فيها استخدام الواجهات. يمكنك استخدامها عندما ترغب في تحديد وفرض هيكل الكائنات التي يتم تمريرها في كودك.

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

تعتبر الواجهات أيضًا مفيدة عند العمل مع الأنواع القابلة لإعادة الاستخدام. عندما تستخدم أجزاء متعددة من تطبيقك كائنات بنفس الهيكل، فإن الواجهات تمنع التكرار.

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

الأنواع العامة والأنواع الحرفية

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

إليك مثال على دالة عامة وواجهة عامة في TypeScript:

// واجهة عامة لصندوق يمكنه احتواء أي قيمة 

interface  Box<T> { 
    value: T; 
}

// أمثلة للاستخدام

let  numberBox: Box<number> = { value: 10 };
let  stringBox: Box<string> = { value: "TypeScript" };

console.log(numberBox.value); // الإخراج: 10  
console.log(stringBox.value); // الإخراج: TypeScript

يمكنك استخدام الأنواع العامة عندما تكون غير متأكد من نوع بياناتك.

بالمقارنة مع التعميمات، أنواع الحرفية تسمح لك بتحديد القيم الدقيقة التي يمكن للمتغير أن يحملها. يضيف ذلك تحديدًا زائدًا وسلامة نوعية إلى كودك، مما يمنع تعيين القيم غير المقصودة. إليك مثالًا:

type Direction = 'up' | 'down' | 'left' | 'right';

يمكن فقط تعيين قيم السلاسل up, down, left, و right لمتغير تم إنشاؤه بنوع الحرفية المذكور أعلاه.

بشكل عام، يمكنك استخدام أنواع مخصصة في TypeScript لإنشاء هياكل بيانات تعبيرية وقابلة لإعادة الاستخدام وآمنة من النوع، مما يساعدك على تطوير تطبيقات أقوى وأسهل الصيانة.

كيفية دمج الأنواع في TypeScript

يجمع دمج الأنواع في TypeScript بين إعلانات أنواع متعددة في نوع واحد موحد. تسمح هذه القدرة للمطورين ببناء أنواع معقدة من قطع صغيرة قابلة لإعادة الاستخدام، مما يعزز وضوح الكود وقابليته لإعادة الاستخدام والصيانة.

1. دمج الإعلانات في الواجهات

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

مثال:
typescriptCopyEditinterface User {
  id: number;
  name: string;
}

interface User {
  email: string;
}

const user: User = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
};
كيف يعمل:
  • تُعلن واجهة User مرتين، كل مرة بخصائص مختلفة.

  • تقوم TypeScript بدمج هذه التصريحات تلقائيًا في واجهة واحدة:

      typescriptCopyEditinterface User {
        id: number;
        name: string;
        email: string;
      }
    
  • عند إنشاء كائن user، يجب أن تكون جميع الخصائص من الواجهة المدمجة موجودة. إذا كانت أي خاصية مفقودة، ستقوم TypeScript بإظهار خطأ.

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

2. دمج الواجهات باستخدام كلمة extends

تسمح كلمة extends لإحدى الواجهات بالوراثة الخصائص والأساليب من أخرى، مما ينشئ واجهة جديدة تجمع بين خصائص كلاهما.

مثال:
typescriptCopyEditinterface Person {
  name: string;
  age: number;
}

interface Employee extends Person {
  employeeId: number;
}

const employee: Employee = {
  name: "John",
  age: 30,
  employeeId: 101,
};
كيف يعمل:
  • تعريف واجهة Person يحدد خاصيتين: name و age.

  • تستخدم واجهة Employee الكلمة المفتاحية extends لتوريث الخصائص من Person.

  • تقوم واجهة Employee أيضًا بإضافة خاصية جديدة، employeeId.

  • يجب أن تتضمن كائن employee جميع الخصائص من كلا Person و Employee.

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

3. دمج الأنواع باستخدام العامل &

العامل &، المعروف باسم نوع التقاطع، يسمح لك بدمج أنواع متعددة في نوع واحد. النوع الناتج يتضمن جميع الخصائص والأساليب من كل نوع.

مثال:
typescriptCopyEdittype Address = {
  city: string;
  country: string;
};

type ContactInfo = {
  email: string;
  phone: string;
};

type EmployeeDetails = Address & ContactInfo;

const employee: EmployeeDetails = {
  city: "New York",
  country: "USA",
  email: "[email protected]",
  phone: "123-456-7890",
};
كيف تعمل:
  • Address و ContactInfo هما نوعان منفصلان.

  • تفاصيل الموظف هو نوع تقاطع تم إنشاؤه باستخدام العنوان & معلومات الاتصال.

  • يجب أن يتضمن كائن الموظف جميع الخصائص من كل من العنوان و معلومات الاتصال. الخصائص المفقودة أو غير المعينة بشكل صحيح ستؤدي إلى خطأ في TypeScript.

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

متى تستخدم كل من هذه الأساليب

  1. دمج التصريحات: استخدمه عندما تريد توسيع أو إضافة إلى واجهة موجودة، خاصة في المكتبات الخارجية أو قواعد التعليمات البرمجية المشتركة.

  2. extends الكلمة الرئيسية: استخدمها للعلاقات الهيكلية حيث يمكن تخصيص واجهة أساسية إلى أنواع أكثر تحديدًا.

  3. أنواع التقاطع (&): استخدمها عندما تحتاج إلى دمج أنواع غير مرتبطة متعددة في نوع واحد لاستخدامات محددة.

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

التجميع والتحويلات في TypeScript

ليس كل متصفح يدعم أحدث JavaScript المستخدم في TypeScript. لذا يمكنك استخدام مترجم TypeScript، أو tsc، لتحويل كود TypeScript (.ts files) إلى JavaScript التقليدي (.js files) المتوافق عالميًا مع جميع المتصفحات. tsc يترجم العناصر الخاصة بـ TypeScript مثل الأنواع والفئات إلى كود JavaScript الذي يمكن أن يفسره المتصفح.

لتنفيذ ملفات TypeScript، tsc هو الخيار المناسب. يمكنك تثبيت tsc باستخدام npm ثم تحويل ملفاتك .ts إلى .js. لاستخدام tsc، فقط حدد اسم ملف TypeScript قبل أمر tsc. على سبيل المثال، إذا كان لديك ملف باسم app.ts، يمكنك تشغيله عن طريق كتابة:

tsc app.ts

غالبًا ما يتم استخدام Webpack أو Parcel لنشر كود TypeScript على المتصفحات. تقوم هذه الأدوات بتجميع جميع ملفات JavaScript، بما في ذلك تلك القادمة من TypeScript، لتحسين الأداء وتسهيل تنفيذ المواقع. كما أنها تعمل على تحسين تحميل الكود من خلال تقليل حجمه وزيادة سرعة المتصفح.

بناء كود أفضل باستخدام TypeScript

يعزز اعتماد TypeScript كمطور JavaScript من إمكانية كتابة كود أكثر متانة وقابلية للصيانة. من خلال فهم الأساسيات والمفاهيم الأساسية المoutlined في هذا الدليل، يمكنك الاستفادة من نظام الكتابة الثابتة في TypeScript لالتقاط الأخطاء مبكرًا في عملية التطوير، مما يؤدي إلى تقليل الأخطاء وسلاسة صيانة الكود.

من خلال استخدام TypeScript، يمكن لمطوري JavaScript تحسين جودة كودهم وإنتاجيتهم. مع استمرارك في استكشاف وممارسة TypeScript، ستكتشف المزيد من الميزات والوظائف القوية.

استمر في دفع حدودك وغص أعمق في عالم TypeScript. 😉