أهلاً بك في هذا القسم الحيوي من رحلتك لتعلم TypeScript، في دورتنا النظرية لتعلم واتقان الـ TypeScript من الصفر.
في الأقسام السابقة، تعرفنا على ماهية TypeScript ولماذا نستخدمها، وقمنا بإعداد بيئة التطوير.
الآن، حان الوقت للغوص في قلب العملية: كيف يتحول كود TypeScript الذي نكتبه إلى JavaScript الذي تفهمه المتصفحات؟
تخيل أنك مهندس معماري عبقري قمت بتصميم مخطط (Blueprint) مذهل لبناء ناطحة سحاب. هذا المخطط دقيق للغاية، ويحتوي على كل التفاصيل والمواصفات التي تضمن أن المبنى سيكون قويًا وآمنًا وخاليًا من العيوب. هذا المخطط هو كود الـ TypeScript الخاص بك.
ولكن، هل يمكن لعمال البناء استخدام هذا المخطط مباشرةً لبناء ناطحة السحاب؟ لا، فهم بحاجة إلى تعليمات تنفيذية بسيطة وواضحة بلغة يفهمونها.
هنا يأتي دور "مدير المشروع" أو "المقاول الرئيسي" الذي يقرأ مخططك المعقد ويترجمه إلى خطوات عمل فعلية ومواد بناء حقيقية. هذا هو JavaScript.
إذًا، من هو هذا الوسيط الذكي الذي يقوم بعملية الترجمة؟
في عالمنا، هذا الوسيط هو مترجم TypeScript (TypeScript Compiler)، والذي نطلق عليه اختصارًا TSC.
في هذا الدرس، سنتعرف بالتفصيل على هذا المترجم السحري (TSC)، وسنتعلم كيف نعطيه التعليمات الدقيقة لتنفيذ عمله عبر ملف خاص يسمى tsconfig.json.
بنهاية هذا القسم، ستكون قادرًا على التحكم الكامل في عملية تحويل كودك من TypeScript إلى JavaScript، وهو ما يمثل حجر الزاوية في بناء أي مشروع باستخدام TypeScript.

ما هو مترجم TypeScript (TSC)؟
ببساطة، مترجم TypeScript أو TSC (TypeScript Compiler) هو أداة تعمل من خلال سطر الأوامر (Command-Line Tool) تأتي مع حزمة TypeScript التي قمنا بتثبيتها سابقًا. مهمته الأساسية مزدوجة:
التحقق من الأنواع (Type Checking):
قبل أي شيء آخر، يقوم TSC بدور المراجع الدقيق. يقرأ كود TypeScript الخاص بك (الموجود في ملفات تنتهي بـ .ts) ويتحقق من أنك تتبع جميع قواعد الأنواع التي حددتها.
هل تحاول إعطاء قيمة رقمية لمتغير يجب أن يكون نصيًا؟ هل استدعيت دالة بمعاملات خاطئة؟ سيقوم TSC باكتشاف هذه الأخطاء وإعلامك بها فورًا.
هذه هي القوة العظمى لـ TypeScript، فهي تمنع الأخطاء قبل حتى أن يتم تشغيل الكود.
الترجمة (Compilation/Transpilation):
بعد التأكد من أن الكود خالٍ من أخطاء الأنواع، يقوم TSC بترجمة أو تحويل (Transpile) كود TypeScript إلى كود JavaScript قياسي. خلال هذه العملية، يقوم بإزالة جميع معلومات الأنواع (مثل :string أو :number) لأن JavaScript لا تفهمها. المنتج النهائي هو ملف JavaScript عادي (ينتهي بـ .js) يمكن تشغيله في أي متصفح ويب أو بيئة Node.js.
استخدام TSC: تجربتك الأولى في الترجمة
دعنا نطبق ما تعلمناه بشكل عملي. لنقم بترجمة أول ملف TypeScript خاص بنا.
الخطوة 1: إنشاء ملف TypeScript
افتح محرر الأكواد الخاص بك وأنشئ ملفًا جديدًا باسم main.ts. لاحظ امتداد الملف هو .ts.
داخل هذا الملف، اكتب الكود البسيط التالي:
// main.ts
// This function greets a user by their name.
// Notice the type annotation: 'personName' must be a string.
function sayHello(personName: string) {
console.log(`Greetings, ${personName}!`);
}
sayHello("Alice"); // This is a valid callهذا كود TypeScript بسيط جدًا. لدينا دالة sayHello تتوقع معاملًا واحدًا personName يجب أن يكون من النوع string.
الخطوة 2: تشغيل المترجم TSC
الآن، افتح الطرفية (Terminal) أو سطر الأوامر في نفس المجلد الذي يوجد به ملف main.ts.
اكتب الأمر التالي واضغط على Enter:
tsc main.tsماذا حدث الآن؟
قام الأمر tsc باستدعاء مترجم TypeScript، وأخبرناه أن الملف الهدف هو main.ts. سيقوم TSC بقراءة الملف، والتحقق منه، ثم… إذا نظرت إلى مجلد مشروعك الآن، ستجد ملفًا جديدًا قد ظهر تلقائيًا: main.js!
الخطوة 3: فحص الملف المُترجَم
افتح ملف main.js الجديد. ستجد بداخله الكود التالي:
// main.js (This file was generated by TSC)
// This function greets a user by their name.
// Notice the type annotation: 'personName' must be a string.
function sayHello(personName) {
console.log("Greetings, ".concat(personName, "!"));
}
sayHello("Alice"); // This is a valid callلاحظ الفرق الجوهري: لقد اختفت : string!
المترجم TSC قام بعمله بنجاح. لقد استخدم معلومة النوع : string للتأكد من صحة الكود، ثم أزالها عند إنشاء ملف JavaScript لأنها ليست جزءًا من لغة JavaScript. قد تلاحظ أيضًا أن طريقة دمج السلاسل النصية تغيرت قليلاً، وهذا يعتمد على إعدادات الترجمة (سنتحدث عنها لاحقًا).
الآن لديك ملف main.js الذي يمكن لأي متصفح أو بيئة Node.js أن تفهمه وتنفذه.
الخطوة 4: رؤية قوة التحقق من الأنواع
دعنا الآن نرى ماذا يحدث عندما نرتكب خطأ. عد إلى ملف main.ts وقم بتغيير استدعاء الدالة ليمرر رقمًا بدلاً من نص:
// main.ts (with a deliberate error)
function sayHello(personName: string) {
console.log(`Greetings, ${personName}!`);
}
// Error! We are passing a number to a function that expects a string.
sayHello(42);احفظ الملف، ثم عد إلى الطرفية وقم بتشغيل أمر الترجمة مرة أخرى:
tsc main.tsهذه المرة، لن تتم العملية بصمت. سيظهر لك TSC خطأً واضحًا في الطرفية، شبيهًا بهذا:
main.ts:8:10 - error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
8 sayHello(42);
~~
Found 1 error.هذا هو سحر TypeScript! لقد أمسك بالخطأ قبل أن يصل إلى مرحلة التنفيذ. يخبرك المترجم بوضوح: "لقد حاولت تمرير number إلى معامل يتوقع string في السطر 8، وهذا غير مسموح به". لقد وفرت على نفسك وقتًا طويلًا في تصحيح الأخطاء (Debugging) التي كان من الممكن أن تحدث في المستقبل.
ملاحظة هامة: بشكل افتراضي، حتى لو وجد TSC خطأ، قد يقوم بإنشاء ملف .js على أي حال. هذا السلوك قابل للتغيير، وعادةً في المشاريع الحقيقية نقوم بضبط المترجم ليتوقف عن إنشاء الملفات إذا كانت هناك أية أخطاء.
الحاجة إلى ملف إعدادات: تقديم tsconfig.json
إن ترجمة ملف واحد في كل مرة باستخدام tsc main.ts تعمل بشكل جيد للمشاريع الصغيرة. ولكن ماذا لو كان مشروعك يحتوي على عشرات أو مئات من ملفات .ts؟
- هل ستقوم بكتابة أسماء جميع الملفات في سطر الأوامر في كل مرة؟ هذا غير عملي.
- ماذا لو أردت تغيير طريقة الترجمة؟ على سبيل المثال، إخراج جميع ملفات
.jsفي مجلد منفصل للحفاظ على تنظيم المشروع؟ - ماذا لو أردت تفعيل أو تعطيل قواعد تحقق معينة؟
هنا يأتي دور ملف tsconfig.json. هذا الملف هو بمثابة الدستور أو كتيب التعليمات لمشروع TypeScript الخاص بك. عندما تقوم بتشغيل الأمر tsc بدون تحديد أي ملف، فإنه يبحث تلقائيًا عن ملف باسم tsconfig.json في المجلد الحالي (والمجلدات الأصلية). إذا وجده، فإنه يقرأ الإعدادات الموجودة بداخله ويطبقها على المشروع بأكمله.
باستخدام tsconfig.json، يمكنك أن تخبر المترجم:
- ما هي الملفات التي يجب عليه ترجمتها.
- ما هي الملفات التي يجب عليه تجاهلها.
- ما هي قواعد التحقق التي يجب تطبيقها.
- إلى أي إصدار من JavaScript يجب أن يترجم الكود.
- أين يجب وضع ملفات JavaScript الناتجة.
- والعديد من الخيارات الأخرى المتقدمة.
إنشاء أول ملف tsconfig.json
إنشاء هذا الملف سهل للغاية. في الطرفية، داخل مجلد مشروعك، قم بتنفيذ الأمر التالي:
tsc --initسيؤدي هذا الأمر إلى إنشاء ملف tsconfig.json جديد في مجلدك. إذا فتحت هذا الملف، قد تشعر بالرهبة قليلاً! ستجده مليئًا بالعديد من الخيارات، معظمها معطل (Commented out) مع شروحات مفيدة.
لا تقلق، لن نحتاج إلى كل هذه الخيارات الآن. سنقوم بالتركيز على أهم الخيارات الأساسية التي تحتاجها لبدء أي مشروع.
تشريح ملف tsconfig.json الأساسي
دعنا نتجاهل الملف الذي تم إنشاؤه تلقائيًا للحظة، وننظر إلى ملف tsconfig.json بسيط ومصغر يوضح الأجزاء الرئيسية:
{
"compilerOptions": {
/* Basic Options */
"target": "es2016",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
/* Strict Type-Checking Options */
"strict": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}هذا الملف مقسم إلى ثلاثة أجزاء رئيسية على المستوى الأعلى: compilerOptions، include، و exclude.
1. compilerOptions - عقل المشروع
هذا هو القسم الأكثر أهمية. إنه كائن (Object) يحتوي على جميع الإعدادات التي تتحكم في كيفية قيام المترجم بعمله. دعنا نشرح الخيارات الأساسية المذكورة أعلاه:
"target": يحدد هذا الخيار إصدار JavaScript (ECMAScript) الذي سيتم إنشاء الكود به. لماذا هذا مهم؟ لأن المتصفحات المختلفة تدعم إصدارات مختلفة من JavaScript. إذا كنت تريد أن يعمل تطبيقك على المتصفحات القديمة جدًا، فقد تختار"es5". إذا كنت تستهدف بيئات حديثة، يمكنك اختيار"es2016"أو"esnext"(الأحدث دائمًا)."module": يحدد نظام الوحدات (Module System) الذي سيتم استخدامه في كود JavaScript الناتج. الوحدات هي طريقة لتقسيم الكود إلى ملفات منفصلة واستيراد (import) وتصدير (export) الوظائف بينها. القيم الشائعة هي"commonjs"(المستخدمة في بيئة Node.js) و"es2015"أو"esnext"(المستخدمة في المتصفحات الحديثة وأدوات التجميع مثل Webpack أو Vite). (سنتعلم المزيد عن الوحدات في قسم لاحق)."outDir": هذا الخيار مهم جدًا لتنظيم المشروع. يخبر المترجم بأن يضع جميع ملفات.jsالناتجة في مجلد محدد. في مثالنا،"./dist"يعني "ضعهم في مجلد اسمهdist". (dist هو اختصار لـ Distributable، أي الكود الجاهز للتوزيع)."rootDir": يحدد هذا الخيار المجلد الجذر الذي يحتوي على ملفات TypeScript المصدرية. عادةً ما يكون"./src"(src هو اختصار لـ Source). يعمل هذا الخيار جنبًا إلى جنب معoutDirللحفاظ على نفس بنية المجلدات. فإذا كان لديك ملف فيsrc/components/button.ts، فسيتم ترجمته إلىdist/components/button.js."strict": هذا خيار واحد لكنه قوي جدًا. عند تعيينه إلىtrue، فإنه يقوم بتفعيل مجموعة كاملة من قواعد التحقق الصارمة من الأنواع. هذا يجبرك على كتابة كود أكثر أمانًا ودقة. كمبتدئ، من أفضل الممارسات دائمًا أن تبدأ بـ"strict": true. إنه مثل تشغيل جميع ميزات الأمان في سيارتك الجديدة.
2. include - ماذا يجب ترجمته؟
هذا القسم عبارة عن مصفوفة (Array) تخبر المترجم ما هي الملفات التي يجب عليه تضمينها في عملية الترجمة. يمكننا استخدام أنماط خاصة تسمى "glob patterns".
في مثالنا، "src/**/*" تعني:
src: ابدأ من داخل مجلدsrc./**/: انظر داخل هذا المجلد وجميع المجلدات الفرعية بداخله (بشكل متكرر).*: طابق أي ملف.
إذًا، "src/**/*" تعني "قم بتضمين جميع الملفات داخل مجلد src وجميع مجلداته الفرعية".
3. exclude - ماذا يجب تجاهله؟
على عكس include، هذه المصفوفة تخبر المترجم بالملفات أو المجلدات التي يجب عليه تجاهلها، حتى لو كانت تطابق أنماط include. هذا مفيد جدًا لتجنب ترجمة أشياء لا نريدها.
في مثالنا، "node_modules" هو أهم مجلد يجب استبعاده. هذا المجلد يحتوي على أكواد المكتبات الخارجية التي نستخدمها، وهي غالبًا ما تكون مكتوبة بـ JavaScript بالفعل ولا تحتاج إلى ترجمة.
سير عمل المشروع النموذجي
الآن دعنا نجمع كل هذه المفاهيم معًا في سير عمل نموذجي لمشروع TypeScript.
1. إعداد هيكل المشروع:
قم بإنشاء مجلد لمشروعك. بداخله، أنشئ مجلدًا باسم src وملف tsconfig.json.
my-typescript-project/
├── src/
│ └── index.ts
└── tsconfig.json2. تكوين tsconfig.json:
ضع الإعدادات الأساسية التي تعلمناها في ملف tsconfig.json:
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true
},
"include": [
"src/**/*"
]
}3. كتابة الكود:
افتح src/index.ts واكتب بعض كود TypeScript:
// src/index.ts
function calculateArea(width: number, height: number): number {
return width * height;
}
const area = calculateArea(10, 20);
console.log(`The area is: ${area}`);4. الترجمة:
الآن، افتح الطرفية في المجلد الرئيسي للمشروع (my-typescript-project). بما أن لدينا ملف tsconfig.json، لم نعد بحاجة لتحديد اسم الملف. ببساطة قم بتشغيل:
tscسيقوم TSC تلقائيًا بالعثور على tsconfig.json، وقراءة الإعدادات، وترجمة جميع الملفات الموجودة في src ووضع النتائج في مجلد dist جديد.
هيكل مشروعك سيبدو الآن هكذا:
my-typescript-project/
├── dist/
│ └── index.js
├── src/
│ └── index.ts
└── tsconfig.json5. وضع المراقبة (Watch Mode): طريقة عمل أكثر ذكاءً
هل من الممل أن تضطر إلى تشغيل tsc في كل مرة تقوم فيها بتغيير في الكود؟ بالتأكيد! لحسن الحظ، لدى TSC حل رائع: وضع المراقبة (Watch Mode).
لتفعيله، أضف العلامة (flag) --watch إلى أمر الترجمة:
tsc --watchعند تشغيل هذا الأمر، لن يتوقف TSC بعد الترجمة الأولى. بدلاً من ذلك، سيظل يعمل في الخلفية ويراقب جميع ملفات .ts الخاصة بك. في اللحظة التي تقوم فيها بحفظ أي تغيير على أي ملف، سيقوم TSC تلقائيًا بإعادة ترجمته على الفور. هذا يعزز الإنتاجية بشكل هائل ويجعل عملية التطوير سلسة وسريعة.
خلاصة
لقد قطعنا شوطًا كبيرًا في هذا القسم! دعنا نلخص النقاط الرئيسية:
مترجم TypeScript (TSC) هو الأداة التي تحول كود TypeScript إلى JavaScript.
يقوم TSC بمهمتين رئيسيتين: التحقق من الأنواع لاكتشاف الأخطاء مبكرًا، والترجمة لإنشاء كود JavaScript متوافق.
يمكننا ترجمة ملف واحد باستخدام tsc filename.ts.
لإدارة المشاريع، نستخدم ملف tsconfig.json الذي يعمل كملف إعدادات مركزي للمترجم.
الأقسام الثلاثة الرئيسية في tsconfig.json هي:
compilerOptions: لتحديد كيفية الترجمة (مثلtarget,outDir,strict).include: لتحديد ماذا يجب ترجمته.exclude: لتحديد ماذا يجب تجاهله.
أفضل الممارسات هي فصل الكود المصدري (في src) عن الكود المترجم (في dist).
استخدام tsc --watch يجعل المترجم يعمل تلقائيًا عند كل تغيير، مما يسرع عملية التطوير.
أنت الآن تملك المعرفة الأساسية للتحكم في أهم أداة في عالم TypeScript. هذه المهارات ستكون الأساس لكل ما ستبنيه لاحقًا. تذكر دائمًا أن tsconfig.json هو صديقك، وكلما فهمته بشكل أفضل، كلما كان كودك أكثر قوة وموثوقية.

