مرحباً بك في هذا القسم الجديد من دورتنا في TypeScript، هذه الدورة النظرية المكتوبة بعناية فائقة لتأخذ بيدك لاتقان الـ TypeScript من البداية.
في الأقسام السابقة، تعرفنا على TypeScript وأهميتها وأعددنا بيئة العمل. الآن، حان الوقت للغوص في صلب الموضوع والبدء في كتابة الكود الفعلي. سنبدأ رحلتنا مع ما يُعرف بـ الأنواع البدائية (Primitive Types).
تخيل أنك تبني منزلاً باستخدام قطع الليغو (LEGO). لديك أنواع مختلفة من القطع: قطع مربعة صغيرة، وقطع مستطيلة طويلة، وقطع مسطحة. كل نوع من هذه القطع له شكل واستخدام محدد. لا يمكنك استخدام قطعة مسطحة لبناء جدار مرتفع، كما لا يمكنك استخدام قطعة مربعة كأساس واسع. هذه القطع هي اللبنات الأساسية التي تُشكّل منها أي هيكل تقوم ببنائه.
في عالم البرمجة، الأنواع البدائية (Primitive Types) هي تماماً مثل قطع الليغو الأساسية. إنها أبسط أنواع البيانات وأكثرها جوهرية، والتي نستخدمها لتشكيل برامجنا وتطبيقاتنا. هي البيانات في صورتها الخام الأولية التي لا يمكن تقسيمها إلى شيء أبسط منها. في JavaScript، اللغة التي بُنيت عليها TypeScript، يوجد عدد من هذه الأنواع. واليوم، سنركز على الثلاثة الأكثر شيوعاً واستخداماً:
- الأرقام (number): لتمثيل البيانات الرقمية، سواء كانت أعداداً صحيحة أو عشرية.
- السلاسل النصية (string): لتمثيل النصوص، مثل الأسماء والرسائل والعناوين.
- القيم المنطقية (boolean): لتمثيل حالتين فقط: صواب (true) أو خطأ (false).
قد تتساءل: "إذا كانت هذه الأنواع موجودة بالفعل في JavaScript، فما الذي تضيفه TypeScript؟" الإجابة تكمن في الصرامة والأمان. في JavaScript، يمكنك إنشاء متغير ليحمل رقماً، ثم في السطر التالي تغير قيمته ليصبح نصاً. هذا قد يسبب أخطاء غير متوقعة وصعبة التتبع في التطبيقات الكبيرة. أما TypeScript، فهي تعمل كحارس أمين؛ عندما تُعرّف متغيراً على أنه سيحمل رقماً، فإن TypeScript تتأكد من أنه سيظل يحمل أرقاماً فقط طوال دورة حياته، وتُنبهك فوراً إذا حاولت وضع نوع بيانات مختلف فيه. هذا هو جوهر "سلامة الأنواع" (Type Safety) التي توفرها TypeScript.
في هذا الدرس المفصل، سنتناول كل نوع من هذه الأنواع الثلاثة على حدة، ونشرحه بالتفصيل مع أمثلة عملية توضح كيفية استخدامه، وكيف تحمينا TypeScript من الأخطاء الشائعة. هيا بنا نبدأ رحلتنا مع أول لبنة أساسية: الأرقام.

النوع الأول: الأرقام (number)
النوع number هو أحد أبسط وأهم الأنواع في TypeScript. نستخدمه لتمثيل أي نوع من البيانات الرقمية. على عكس بعض لغات البرمجة الأخرى التي قد تحتوي على أنواع مختلفة للأرقام (مثل int للأعداد الصحيحة، وfloat للأعداد العشرية)، فإن TypeScript (مثل JavaScript) لديها نوع واحد فقط هو number يشمل كل هذه الحالات.
كيفية تعريف متغير من النوع number
لإخبار TypeScript بأن متغيراً ما سيحتوي على قيمة رقمية، نستخدم الصيغة التالية: نكتب اسم المتغير، ثم نقطتين رأسيتين (:), ثم كلمة number.
// Declaring a variable 'userAge' that will hold a number.
let userAge: number;
// Now we can assign a number to it.
userAge = 30;
// We can also declare and initialize in the same line.
let productPrice: number = 199.99;في المثال أعلاه، أعلنا أن المتغير userAge سيحمل قيمة من النوع number. أي محاولة لوضع قيمة من نوع آخر (مثل نص) في هذا المتغير ستؤدي إلى خطأ من مترجم TypeScript، وهو ما سنراه بعد قليل.
أشكال الأرقام المدعومة
النوع number في TypeScript مرن جداً ويدعم جميع أشكال الأرقام التي قد تحتاجها:
الأعداد الصحيحة (Integers): الأرقام الكاملة بدون كسور.
الأعداد العشرية (Floating-Point Numbers): الأرقام التي تحتوي على فاصلة عشرية.
الصيغة العلمية (Scientific Notation): لتمثيل الأرقام الكبيرة جداً أو الصغيرة جداً.
النظام الست عشري (Hexadecimal): تبدأ بـ
0x.النظام الثنائي (Binary): تبدأ بـ
0b.النظام الثماني (Octal): تبدأ بـ
0o.
typescript let octalPermissions: number = 0o755; console.log(octalPermissions); // Outputs: 493
let numberOfItems: number = 150;let piValue: number = 3.14159;
let accountBalance: number = -55.20; // It can be negative too// Represents 5 billion (5 with 9 zeros)
let earthPopulation: number = 7.8e9;
console.log(earthPopulation); // Outputs: 7800000000let hexColorCode: number = 0xff0000; // Represents the color red
console.log(hexColorCode); // Outputs: 16711680let binaryFlag: number = 0b1010;
console.log(binaryFlag); // Outputs: 10كيف تحمينا TypeScript؟
الآن لنرَ القوة الحقيقية لـ TypeScript. تخيل أنك تقوم ببناء تطبيق لمتجر إلكتروني، ولديك متغير لحساب السعر الإجمالي. لقد حددت نوعه ليكون number.
let totalCost: number;
totalCost = 500; // This is perfectly fine.
console.log(totalCost); // Outputs: 500لنفترض أنك ارتكبت خطأً عن غير قصد وحاولت إسناد قيمة نصية إليه.
// The following line will immediately show an error in your code editor!
// It will not even compile.
totalCost = "Free Shipping"; // ERROR!سيقوم مترجم TypeScript بإظهار خطأ واضح وصريح قبل حتى أن تقوم بتشغيل الكود، قائلاً:
Error: Type 'string' is not assignable to type 'number'.
هذا يعني: "خطأ: لا يمكن إسناد القيمة من النوع 'string' إلى متغير من النوع 'number'." هذه الميزة الصغيرة وحدها يمكن أن تمنع عدداً لا يحصى من الأخطاء التي قد تحدث في تطبيقات JavaScript الكبيرة، حيث قد يتسبب خطأ بسيط كهذا في انهيار جزء من التطبيق أو إظهار نتائج غير متوقعة للمستخدم (مثل NaN أو Not a Number).
النوع الثاني: السلاسل النصية (string)
بعد أن فهمنا الأرقام، ننتقل إلى اللبنة الأساسية الثانية: السلاسل النصية (string). نستخدم هذا النوع لتمثيل أي بيانات نصية، من حرف واحد إلى كتاب كامل. أي شيء تضعه بين علامات اقتباس يعتبر سلسلة نصية.
كيفية تعريف متغير من النوع string
بنفس الطريقة التي عرفنا بها الأرقام، نستخدم النقطتين الرأسيتين (:) متبوعة بكلمة string.
/ Declaring a variable that will hold a string.
let customerName: string;
customerName = "Fatima Al-Fihri";
// Or in one line:
let websiteTitle: string = "My Awesome Blog";طرق كتابة السلاسل النصية
في TypeScript، لديك ثلاث طرق مختلفة لإنشاء السلاسل النصية، كل منها مفيد في سياقات مختلفة.
علامات الاقتباس المزدوجة (Double Quotes)
علامات الاقتباس المفردة (Single Quotes)
قوالب النصوص (Template Literals)هذه هي الطريقة الأحدث والأكثر قوة. نستخدم فيها العلامة المائلة للخلف (backtick)
``. ما يميزها هو قدرتها على أمرين رائعين:السلاسل متعددة الأسطر (Multi-line Strings): يمكنك كتابة نص يمتد على عدة أسطر دون الحاجة إلى رموز خاصة.
تضمين التعبيرات (Embedded Expressions): يمكنك إدراج قيم المتغيرات أو حتى تنفيذ عمليات حسابية بسيطة مباشرة داخل السلسلة النصية باستخدام الصيغة
${...}.
let bookTitle: string = "The Art of Programming";let authorName: string = 'John Doe';لا يوجد فرق وظيفي بين استخدام علامات الاقتباس المفردة أو المزدوجة. الأمر يعود إلى تفضيل المبرمج أو إرشادات الأسلوب المتبعة في المشروع. القاعدة العامة هي اختيار أسلوب واحد والالتزام به للحفاظ على تناسق الكود.
let emailTemplate: string = `
Hello user,
Thank you for registering on our platform.
Best regards,
The Support Team
`;
console.log(emailTemplate);كما ترى، تم الحفاظ على المسافات والأسطر الجديدة كما هي، مما يجعل كتابة النصوص الطويلة أسهل بكثير.
let userName: string = "Ali";
let userPoints: number = 150;
// Instead of old-style string concatenation:
// let welcomeMessage = "Welcome, " + userName + "! You have " + userPoints + " points.";
// We can use the much cleaner template literal:
let welcomeMessage: string = `Welcome, ${userName}! You have ${userPoints} points.`;
console.log(welcomeMessage); // Outputs: Welcome, Ali! You have 150 points.
// You can even put expressions inside
let itemPrice: number = 250;
let quantity: number = 3;
let orderSummary: string = `Your total is: $${itemPrice * quantity}`;
console.log(orderSummary); // Outputs: Your total is: $750هذه الميزة تجعل الكود أكثر قابلية للقراءة وأقل عرضة للأخطاء مقارنةً بالطريقة التقليدية لدمج النصوص باستخدام عامل +.
كيف تحمينا TypeScript؟
مرة أخرى، تعمل TypeScript كحارس أمن. لنفترض أنك تعمل على نظام إدارة محتوى ولديك متغير لعنوان المقالة.
let articleTitle: string;
articleTitle = "An Introduction to TypeScript"; // Correctإذا حاول مبرمج آخر (أو أنت عن طريق الخطأ) إسناد رقم معرف المقالة إلى هذا المتغير:
// This will result in a compile-time error
articleTitle = 101; // ERROR!سيظهر الخطأ الفوري:
Error: Type 'number' is not assignable to type 'string'.
هذا يمنع الأخطاء التي قد تحدث لاحقًا إذا حاولت استخدام articleTitle كأنه نص (على سبيل المثال، محاولة قراءة خاصية length عليه، والتي لا توجد في الأرقام)، مما كان سيؤدي إلى انهيار البرنامج في وقت التشغيل (runtime).
النوع الثالث: القيم المنطقية (boolean)
النوع البدائي الأخير الذي سنتناوله اليوم هو القيم المنطقية (boolean). هذا النوع بسيط للغاية ولكنه أساسي في البرمجة. يمكن أن يحمل قيمتين فقط لا غير: true (صواب) أو false (خطأ).
فكر في مفتاح الإضاءة في غرفتك. يمكن أن يكون في إحدى حالتين فقط: إما "تشغيل" (ON) أو "إطفاء" (OFF). لا توجد حالة وسط. هذا هو بالضبط ما يمثله النوع boolean.
يُستخدم هذا النوع بشكل أساسي للتحكم في تدفق البرنامج (Control Flow) واتخاذ القرارات بناءً على شروط معينة.
كيفية تعريف متغير من النوع boolean
// Declaring a variable that will hold a boolean value.
let isUserLoggedIn: boolean;
isUserLoggedIn = true;
// Or in one line:
let isContentPublished: boolean = false;الاستخدام العملي للقيم المنطقية
تظهر قوة القيم المنطقية عند استخدامها مع الجمل الشرطية مثل if/else.
let hasAdminRights: boolean = false;
let currentUser: string = "Guest";
if (hasAdminRights) {
console.log(`Welcome Admin! You have full control.`);
} else {
console.log(`Welcome ${currentUser}! You have limited access.`);
}
// The output will be: Welcome Guest! You have limited access.في هذا المثال، يتحكم المتغير hasAdminRights في الرسالة التي يتم عرضها. إذا غيرنا قيمته إلى true، سيتغير سلوك البرنامج تمامًا.
كيف تحمينا TypeScript؟
في JavaScript العادية، هناك مفهوم يسمى "truthy" و "falsy". على سبيل المثال، الرقم 1 يعتبر "truthy" بينما الرقم 0 يعتبر "falsy". هذا يمكن أن يؤدي إلى ارتباك وأخطاء.
// In plain JavaScript, this is possible but can be confusing
// if (1) { console.log('This will run'); }
// if (0) { console.log('This will not run'); }TypeScript تفرض عليك أن تكون أكثر دقة ووضوحاً. إذا حددت أن متغيراً من نوع boolean، فيجب أن تكون قيمته true أو false حصراً.
let isTaskCompleted: boolean;
isTaskCompleted = true; // Correct
isTaskCompleted = false; // Also correct
// The following lines will all cause errors in TypeScript!
isTaskCompleted = 1; // ERROR: Type 'number' is not assignable to type 'boolean'.
isTaskCompleted = "true"; // ERROR: Type 'string' is not assignable to type 'boolean'.
isTaskCompleted = null; // ERROR: Type 'null' is not assignable to type 'boolean'.هذه الصرامة تجبرك على كتابة كود أكثر وضوحًا وأقل غموضًا. إذا كان الشرط يعتمد على حالة صواب أو خطأ، فيجب أن تكون القيمة المستخدمة هي true أو false بشكل صريح، مما يزيل أي مجال للشك أو التفسيرات غير المقصودة.
ملاحظة مهمة: الاستدلال على النوع (Type Inference)
قد تلاحظ في بعض الأكواد أن المبرمجين لا يكتبون النوع بشكل صريح دائمًا، مثل let name = "Sara"; بدلاً من let name: string = "Sara";. فهل هذا يعني أنهم لا يستخدمون TypeScript بشكل صحيح؟
الإجابة هي لا. هذا بسبب ميزة ذكية في TypeScript تسمى الاستدلال على النوع (Type Inference). عندما تقوم بتعريف متغير وإعطائه قيمة أولية في نفس السطر، فإن TypeScript ذكية بما يكفي لتفهم نوع هذا المتغير من القيمة التي أعطيتها له.
// Here, TypeScript sees the value "MacBook Pro"
// and automatically understands (infers) that `productName` is of type 'string'.
let productName = "MacBook Pro";
// If you try to assign a number now, it will still give you an error.
// productName = 16; // ERROR: Type 'number' is not assignable to type 'string'.
// TypeScript infers 'inventoryCount' is of type 'number'.
let inventoryCount = 50;
// TypeScript infers 'inStock' is of type 'boolean'.
let inStock = true;متى يجب أن تكتب النوع صراحةً؟
من الممارسات الجيدة كتابة النوع بشكل صريح في حالتين رئيسيتين:
عندما تُعرّف متغيراً دون إعطائه قيمة أولية. هنا، يجب أن تخبر TypeScript بنوع القيمة التي سيحملها هذا المتغير في المستقبل.
عندما تريد أن يكون النوع أكثر تحديداً أو تعقيداً، وهو ما سنتعلمه في الدروس القادمة (مثل
Union Types).
let shippingAddress: string; // We must specify the type here.
// ... some logic happens ...
shippingAddress = "123 Main St, Anytown";بشكل عام، الاعتماد على الاستدلال على النوع يجعل الكود أنظف وأقصر، ولكن التصريح الصريح عن النوع يجعله أكثر وضوحاً للقارئ، خاصة للمبتدئين.
خلاصة
في هذا الدرس، وضعنا الأساس لفهم كيفية تعامل TypeScript مع البيانات. تعلمنا عن الأنواع البدائية الثلاثة الأكثر أهمية:
number: لجميع أنواع الأرقام، سواء كانت صحيحة، عشرية، أو بأي نظام عددي آخر.string: لجميع أشكال النصوص، مع طرق قوية لإنشائها وتنسيقها باستخدام علامات الاقتباس المختلفة وقوالب النصوص.boolean: للقيم المنطقيةtrueوfalse، وهي حجر الزاوية في اتخاذ القرارات داخل برامجنا.
الأهم من ذلك، رأينا كيف أن TypeScript لا تقدم فقط هذه الأنواع، بل تفرض استخدامها بشكل صحيح. من خلال التحقق من الأنواع في وقت الترجمة (Compile Time)، تمنعنا TypeScript من ارتكاب فئة كاملة من الأخطاء الشائعة في JavaScript، مما يجعل تطبيقاتنا أكثر قوة وموثوقية وسهولة في الصيانة.
أنت الآن تمتلك اللبنات الأساسية. في الدروس القادمة، سنتعرف على أنواع أخرى أكثر تخصصًا وتعقيدًا، وسنبدأ في بناء هياكل بيانات أكثر ثراءً باستخدام هذه الأساسيات. استمر في الممارسة، وجرب تعريف متغيرات من هذه الأنواع المختلفة وحاول إسناد قيم خاطئة لترى أخطاء TypeScript بنفسك.

