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

ما هي TypeScript؟
TypeScript هي لغة برمجة طورتها وتدعمها شركة Microsoft. ويمكن وصفها بأنها امتداد للغة JavaScript، لأنها تحتوي على جميع خصائصها تقريباً، مع إضافة ميزات مهمة مثل التحقق الصارم من الأنواع Type Checking والتحليل الثابت للشيفرة Static Analysis.
بعد كتابة الشيفرة باستخدام TypeScript، يتم تحويلها إلى شيفرة JavaScript عادية يمكن للمتصفح أو بيئة التشغيل تنفيذها. لهذا السبب تُعد خياراً ممتازاً عند بناء تطبيقات كبيرة أو فرق عمل تحتاج إلى شيفرة أوضح وأسهل في الصيانة.
الأركان الأساسية في TypeScript
1. اللغة نفسها Language
يشمل ذلك الصياغة Syntax، والكلمات المحجوزة، وتعريف الأنواع Type Annotations. تشبه صياغة TypeScript إلى حد كبير JavaScript، لكنها تضيف طبقة تنظيمية مفيدة جداً.
2. المترجم Compiler
المترجم مسؤول عن تحويل شيفرة TypeScript إلى JavaScript. ومن الأدق تقنياً وصف هذه العملية بأنها Transpiling، لأنها تنقل الشيفرة من لغة عالية المستوى إلى لغة عالية المستوى أخرى، بدلاً من تحويلها مباشرة إلى لغة آلة.
كما يقوم المترجم بحذف معلومات الأنواع أثناء التحويل، لأن المتصفح لا يفهم الأنواع مثل string وnumber داخل شيفرة JavaScript النهائية.
3. خدمة اللغة Language Service
هذه الخدمة هي ما يمنحك مزايا ذكية داخل المحررات مثل VS Code، ومنها:
- الإكمال التلقائي
IntelliSense - تلميحات الأنواع
- اقتراحات إعادة الهيكلة
Refactoring - اكتشاف الأخطاء أثناء الكتابة
أهم مزايا TypeScript
إضافة الأنواع Type Annotations
تعني إضافة نوع واضح للمتغير أو للدالة، حتى يعرف المترجم ما القيم المتوقعة وما النتائج الصحيحة.
const birthdayGreeter = (name: string, age: number): string => {
return `Happy birthday ${name}, you are now ${age} years old!`;
};
const birthdayHero = "Jane User";
const age = 22;
console.log(birthdayGreeter(birthdayHero, 22));
في المثال السابق، الدالة birthdayGreeter تستقبل وسيطين:
nameمن النوعstringageمن النوعnumber
كما أن القيمة المعادة من الدالة محددة بأنها من النوع string. وإذا مرّرت نوعاً مختلفاً، فسيعرض TypeScript خطأ قبل تشغيل التطبيق.
const birthdayGreeter = (name: string, age: number): string => {
};
الكتابة الهيكلية Structural Typing
تعتمد TypeScript على مفهوم مهم يُعرف باسم Structural Typing. والمقصود به أن النوع لا يُحدَّد فقط بالاسم، بل ببنية العنصر وخصائصه. فإذا كان كائنان يمتلكان الخصائص نفسها، فقد يُعتبران من النوع نفسه من منظور اللغة.
استنتاج الأنواع Type Inference
ليست هناك حاجة دائماً إلى كتابة النوع يدوياً، لأن TypeScript قادرة في كثير من الحالات على استنتاجه تلقائياً من القيمة أو من طريقة الاستخدام.
const platform = 'freeCodeCamp';
const add = (a: number, b: number) => a + b;
في هذا المثال، يستنتج المترجم أن platform من النوع string، كما يستنتج أن قيمة الإرجاع في الدالة add هي number.
حذف الأنواع عند التحويل Type Erasure
عند تحويل الشيفرة، تتم إزالة معلومات الأنواع لأنها غير مدعومة مباشرة في JavaScript.
المدخل:
let x: someType;
المخرج:
let x;
لماذا يُنصح باستخدام TypeScript؟
تقليل الأخطاء البرمجية
يساعد التحقق من الأنواع والتحليل الثابت للشيفرة على اكتشاف كثير من الأخطاء مبكراً، مثل تمرير قيمة خاطئة إلى دالة أو كتابة اسم متغير بشكل غير صحيح. هذا يعني وقتاً أقل في تتبع المشكلات داخل بيئة الإنتاج.
توثيق الشيفرة بشكل ضمني
عندما ترى دالة تستقبل string وتعيد number، فإنك تفهم سلوكها بسرعة حتى قبل قراءة تفاصيل التنفيذ. لذلك تُعد الأنواع وسيلة ممتازة لتوثيق الشيفرة ورفع قابليتها للفهم داخل الفرق التقنية.
تحسين تجربة التطوير
كلما كانت الأنواع أوضح، أصبحت أدوات التطوير أذكى. وستحصل على اقتراحات دقيقة، وتنقل أسرع داخل المشروع، وتنبيهات فورية عند وجود تعارض في استخدام البيانات.
كيفية البدء باستخدام TypeScript
تثبيت الحزمة
يمكنك تثبيت TypeScript بطريقتين: إما بشكل عام على النظام، أو داخل مشروع محدد فقط.
للتثبيت العام:
npm install -g typescript
للتثبيت المحلي داخل المشروع:
npm install --save-dev typescript
يفضل كثير من المطورين التثبيت المحلي، لأن TypeScript تُستخدم غالباً أثناء التطوير فقط، ثم تُحوَّل الشيفرة لاحقاً إلى JavaScript قبل النشر.
تهيئة المشروع
بعد التثبيت، يمكنك إنشاء ملف الإعدادات الأساسي عبر الأمر التالي:
tsc --init
ينتج عن هذا الأمر ملف tsconfig.json في المجلد الرئيسي للمشروع، وهو الملف المسؤول عن إعداد خيارات الترجمة والسلوك العام للغة داخل المشروع.

داخل ملف tsconfig.json يمكنك تخصيص خيارات متعددة، مثل مستوى الصرامة، ومسار الملفات، وطريقة إخراج الشيفرة المترجمة. ويمكنك حذف أو تعطيل أي خيار لا تحتاج إليه.
أنواع البيانات المدمجة في TypeScript
توفر TypeScript الأنواع الأساسية الموجودة في JavaScript مثل:
stringnumberboolean
ويمكن إسناد هذه الأنواع إلى المتغيرات بشكل مباشر:
const myName: string = 'Joel';
const myAge: number = 99;
لكن في كثير من الحالات لن تحتاج إلى كتابة النوع يدوياً، لأن اللغة ستستنتجه تلقائياً:
// myName is inferred type 'string'
const myName = 'Jonathan';
المصفوفات في TypeScript
لتحديد نوع المصفوفة يمكنك استخدام الصياغة string[] أو number[]. كما يمكنك استخدام الصياغة البديلة Array<string> أو Array<number>، وكلاهما صحيح.
string[]تعني مصفوفة من النصوصnumber[]تعني مصفوفة من الأرقام
أنواع الاتحاد Union Types
تتيح لك أنواع الاتحاد تعريف أكثر من نوع مقبول للمتغير نفسه، وذلك باستخدام الرمز |.
const someValue: number | string = value;
هذا يعني أن المتغير someValue يمكن أن يحمل قيمة رقمية أو نصية.
ومن المفاهيم المرتبطة بذلك التعامل مع null وundefined. وعند تفعيل الخيار strictNullChecks، تمنع TypeScript إسناد هاتين القيمتين بشكل عشوائي، مما يرفع مستوى الأمان في الشيفرة.
الدوال في TypeScript
يمكن للدوال أن تستقبل أنواعاً محددة للوسائط، كما يمكن تحديد نوع القيمة المعادة منها.
function introduction(name: string, age: number): string {
return `Hello, my name is ${name} and I'm ${age} years old`;
}
إذا كانت الدالة لا تعيد أي قيمة، يمكنك استخدام النوع void.
كما تدعم TypeScript الوسائط الاختيارية باستخدام ?، بالإضافة إلى القيم الافتراضية.
const introduction = (name: string, age: number, job: string = 'developer'): string =>
`Hello, my name is ${name} and I'm ${age} years old. I work as a ${job}`;
ومن الأفضل ملاحظة أن القيمة الافتراضية تجعل تمرير الوسيط عملياً اختيارياً في هذا المثال.
النوع any ولماذا يجب الحذر منه
عندما لا تستطيع TypeScript استنتاج نوع متغير ما، فقد تعتبره من النوع any. وهذا النوع يعني عملياً أن المتغير يمكن أن يحمل أي قيمة بدون قيود واضحة.
ورغم أن any قد يكون مفيداً في بعض الحالات الخاصة، فإن الإفراط في استخدامه يلغي كثيراً من فوائد TypeScript. لذلك يُنصح بتفعيل الخيار noImplicitAny حتى تظهر لك الأخطاء عند استخدام هذا النوع بشكل غير مقصود.
كيفية إنشاء أنواع مخصصة
استخدام الكلمة المفتاحية type
يمكنك إنشاء أنواعك الخاصة لتحديد قيم دقيقة ومحددة مسبقاً.
type Operator = 'multiply' | 'add' | 'divide';
النوع Operator في هذا المثال لا يقبل إلا واحدة من ثلاث قيم فقط، وهذا أسلوب عملي جداً عند بناء واجهات إدخال أو أوامر محددة.
مثال عملي: آلة حاسبة بسيطة
في المثال التالي سنستخدم نوعاً مخصصاً لبناء دالة آلة حاسبة تنفذ ثلاث عمليات فقط:
type Operation = 'multiply' | 'add' | 'divide';
const calculator = (a: number, b: number, op: Operation): number | string => {
switch (op) {
case 'multiply':
return a * b;
case 'add':
return a + b;
case 'divide':
if (b === 0) return "Can't divide by 0";
return a / b;
default:
return 'Operation unknown';
}
};
هذا المثال يوضح قيمة الأنواع المخصصة في تقليل الخيارات غير الصالحة، ومنع تمرير عمليات غير متوقعة إلى الدالة.
استخدام interface لتعريف الكائنات
تسمح لك interface بتحديد شكل الكائن وخصائصه وأنواعها، كما يمكنها أن ترث من interface أخرى.
interface Employee {
name: string;
title: string;
}
interface Manager extends Employee {
meeting: (topic: string) => void;
}
في هذا المثال:
Employeeيعرّف خصيصتين هماnameوtitleManagerيرث الخصائص السابقة ويضيف الدالةmeeting
ويمكننا استخدام هذه الواجهة بالشكل التالي:
const newEmployee: Employee = {
name: 'Joel',
title: 'FrontEnd Developer'
};
إذا احتوى كائن ما على الخصائص المطلوبة، فغالباً يمكن التعامل معه على أنه يحقق هذه الواجهة، حتى لو كانت لديه خصائص إضافية.
ما الفرق بين type وinterface؟
كلاهما يُستخدم لتعريف أنواع مخصصة، لكن هناك فرقاً مهماً:
- يمكن دمج أكثر من تعريف يحمل الاسم نفسه عند استخدام
interface - أما مع
typeفإن تكرار الاسم نفسه يؤدي عادة إلى خطأ
بشكل عملي، يُفضّل كثير من المطورين استخدام interface عند وصف الكائنات، واستخدام type عند بناء اتحادات الأنواع أو التركيبات الأكثر مرونة.
أفضل ممارسات للمبتدئين في TypeScript
- ابدأ بتفعيل الإعدادات الصارمة مثل
strictكلما أمكن. - تجنب استخدام
anyإلا عند الضرورة. - اعتمد على استنتاج الأنواع عندما يكون واضحاً، ولا تكرر ما هو بديهي.
- استخدم
typeوinterfaceلتوضيح بنية البيانات في المشروع. - راجع ملف
tsconfig.jsonجيداً لأنه يؤثر مباشرة في جودة التجربة التطويرية.
الخلاصة التقنية
TypeScript ليست مجرد إضافة تجميلية فوق JavaScript، بل أداة عملية ترفع جودة الشيفرة وتمنح المطور قدرة أكبر على اكتشاف الأخطاء مبكراً وتنظيم المشاريع الكبيرة بكفاءة. وإذا كنت تبدأ الآن في تطوير تطبيقات حديثة للويب، فإن تعلم TypeScript مبكراً يعد استثماراً تقنياً ممتازاً سيوفر عليك كثيراً من الوقت والمشكلات مع توسع المشروع.