TypeScript

الأنواع الأساسية في TypeScript — دليل شامل 2026

📅 2026-10-02⏱ 11 دقائق قراءة
في المقال السابق، كتبت أول برنامج TypeScript واستخدمت بعض الأنواع الأساسية. الآن حان الوقت للتعمق في **نظام الأنواع** — وهو ما يميز TypeScript عن JavaScript. في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم جميع الأنواع الأساسية في TypeScript، مع تمارين وحلول. ## ما هو نظام الأنواع؟ نظام الأنواع هو **مجموعة من القواعد** التي تحدد: - **ما نوع القيمة** التي يمكن تخزينها في متغير. - **ما العمليات** التي يمكن إجراؤها على هذه القيمة. - **ما الأخطاء** التي يمكن اكتشافها قبل التشغيل. **مثال بسيط:** ```typescript let age: number = 25; // ✅ صحيح let age: number = "25"; // ❌ خطأ: النوع مختلف ``` **الفائدة:** تكتشف الأخطاء **قبل** تشغيل الكود. ## لماذا نحتاج نظام الأنواع؟ - **الأمان:** تكتشف الأخطاء مبكراً. - **التوثيق:** الكود يوثق نفسه. - **الأدوات:** إكمال تلقائي (IntelliSense) أفضل. - **إعادة الهيكلة:** تغيير الكود بأمان. - **التعاون:** الفريق يفهم الكود بسهولة. ## الأنواع البدائية (Primitive Types) ### 1. `string` — النصوص ```typescript let firstName: string = "أحمد"; let lastName: string = 'محمد'; let greeting: string = `مرحباً ${firstName}`; console.log(firstName); // أحمد console.log(greeting); // مرحباً أحمد ``` **عمليات على النصوص:** ```typescript let text: string = "TypeScript"; console.log(text.length); // 10 console.log(text.toUpperCase()); // TYPESCRIPT console.log(text.toLowerCase()); // typescript console.log(text.charAt(0)); // T console.log(text.includes("Script")); // true ``` ### 2. `number` — الأرقام الأرقام في TypeScript تشمل الصحيحة والعشرية (لا يوجد نوع منفصل للأعداد الصحيحة). ```typescript let age: number = 25; let price: number = 99.99; let temperature: number = -5; let hex: number = 0xff; // 255 let binary: number = 0b1010; // 10 let octal: number = 0o777; // 511 ``` **عمليات حسابية:** ```typescript let a: number = 10; let b: number = 3; console.log(a + b); // 13 console.log(a - b); // 7 console.log(a * b); // 30 console.log(a / b); // 3.333... console.log(a % b); // 1 console.log(a ** b); // 1000 ``` ### 3. `boolean` — القيم المنطقية ```typescript let isStudent: boolean = true; let isMarried: boolean = false; let hasJob: boolean = true; if (isStudent) { console.log("أنت طالب"); } ``` ### 4. `null` و `undefined` ```typescript let nothing: null = null; let notDefined: undefined = undefined; ``` **⚠️ ملاحظة:** مع `strict: true` في `tsconfig.json`، `null` و `undefined` لهما أنواع خاصة. ### 5. `bigint` — الأرقام الكبيرة ```typescript let bigNumber: bigint = 9007199254740991n; let anotherBig: bigint = BigInt("9007199254740991"); ``` **متى تستخدمه؟** عندما تحتاج أرقاماً أكبر من `Number.MAX_SAFE_INTEGER`. ### 6. `symbol` — الرموز ```typescript let sym1: symbol = Symbol("key"); let sym2: symbol = Symbol("key"); console.log(sym1 === sym2); // false (كل Symbol فريد) ``` ## الأنواع المركبة (Composite Types) ### 1. المصفوفات (Arrays) **طريقة 1: `type[]`** ```typescript let numbers: number[] = [1, 2, 3, 4, 5]; let names: string[] = ["أحمد", "محمد", "علي"]; let flags: boolean[] = [true, false, true]; ``` **طريقة 2: `Array<type>`** ```typescript let numbers: Array<number> = [1, 2, 3]; let names: Array<string> = ["أحمد", "محمد"]; ``` **مصفوفة مختلطة:** ```typescript let mixed: (string | number)[] = ["أحمد", 25, "علي", 30]; ``` **عمليات على المصفوفات:** ```typescript let fruits: string[] = ["تفاح", "موز"]; fruits.push("برتقال"); // إضافة fruits.pop(); // حذف من النهاية fruits.unshift("عنب"); // إضافة في البداية fruits.shift(); // حذف من البداية console.log(fruits.length); // عدد العناصر console.log(fruits.includes("موز")); // true ``` ### 2. Tuples — المصفوفات ذات الطول الثابت Tuple هي مصفوفة تعرف **عدد عناصرها** و **نوع كل عنصر** مقدماً. ```typescript let point: [number, number] = [10, 20]; let user: [string, number, boolean] = ["أحمد", 25, true]; console.log(point[0]); // 10 console.log(user[0]); // أحمد ``` **الفرق بين Array و Tuple:** ```typescript // Array: أي عدد من العناصر let arr: number[] = [1, 2, 3, 4, 5, 6, 7]; // Tuple: عدد محدد من العناصر let tuple: [number, number] = [10, 20]; // let tuple: [number, number] = [10, 20, 30]; // ❌ خطأ ``` ### 3. الكائنات (Objects) ```typescript let person: { name: string; age: number; isStudent: boolean; } = { name: "أحمد", age: 25, isStudent: true, }; console.log(person.name); // أحمد console.log(person.age); // 25 console.log(person.isStudent); // true ``` **خصائص اختيارية:** ```typescript let user: { name: string; email?: string; // اختياري } = { name: "أحمد", }; user.email = "ahmed@example.com"; // ✅ مسموح ``` **خصائص للقراءة فقط:** ```typescript let config: { readonly apiKey: string; url: string; } = { apiKey: "abc123", url: "https://api.example.com", }; config.url = "https://new-api.com"; // ✅ // config.apiKey = "new-key"; // ❌ خطأ: readonly ``` ## الأنواع الخاصة (Special Types) ### 1. `any` — أي نوع (تجنبه!) ```typescript let data: any = "نص"; data = 25; // ✅ data = true; // ✅ data = [1, 2, 3]; // ✅ data = { x: 1 }; // ✅ ``` **⚠️ تحذير:** `any` يلغي كل فوائد TypeScript. استخدمه فقط عند الضرورة القصوى. ### 2. `unknown` — البديل الآمن لـ `any` ```typescript let data: unknown = "نص"; // console.log(data.toUpperCase()); // ❌ خطأ if (typeof data === "string") { console.log(data.toUpperCase()); // ✅ } ``` **الفرق:** `unknown` يطلب منك التحقق من النوع قبل الاستخدام. ### 3. `void` — لا قيمة مرجعة ```typescript function logMessage(message: string): void { console.log(message); } const result = logMessage("مرحباً"); console.log(result); // undefined ``` ### 4. `never` — لا يحدث أبداً ```typescript function throwError(message: string): never { throw new Error(message); } function infiniteLoop(): never { while (true) { // ... } } ``` **متى تستخدم `never`؟** - دالة ترمي خطأ دائماً. - دالة بحلقة لا نهائية. - في التحقق الشامل (exhaustive check). ### 5. `object` — أي كائن غير بدائي ```typescript let obj: object = { name: "أحمد" }; // let obj: object = "نص"; // ❌ خطأ ``` ## أنواع الاتحاد (Union Types) Union تسمح لمتغير بأن يكون **أحد عدة أنواع**. ```typescript let id: string | number; id = "ABC123"; // ✅ id = 12345; // ✅ // id = true; // ❌ خطأ ``` **مثال عملي:** ```typescript function printId(id: string | number): void { if (typeof id === "string") { console.log("ID نصي:", id.toUpperCase()); } else { console.log("ID رقمي:", id); } } printId("ABC123"); // ID نصي: ABC123 printId(12345); // ID رقمي: 12345 ``` ## أنواع التقاطع (Intersection Types) Intersection تدمج عدة أنواع في نوع واحد. ```typescript type Person = { name: string; age: number; }; type Employee = { company: string; salary: number; }; type EmployeePerson = Person & Employee; const emp: EmployeePerson = { name: "أحمد", age: 25, company: "Google", salary: 50000, }; ``` ## الأنواع الحرفية (Literal Types) Literal Types تحدّد القيم المسموح بها. ```typescript let direction: "north" | "south" | "east" | "west"; direction = "north"; // ✅ direction = "up"; // ❌ خطأ ``` **مثال عملي:** ```typescript type Status = "pending" | "approved" | "rejected"; function updateStatus(status: Status): void { console.log("الحالة: " + status); } updateStatus("approved"); // ✅ // updateStatus("unknown"); // ❌ خطأ ``` ## Enums — التعدادات Enum هي طريقة لتعريف مجموعة من الثوابت. ### 1. Enum رقمي ```typescript enum Direction { North, South, East, West, } let dir: Direction = Direction.North; console.log(dir); // 0 console.log(Direction[0]); // "North" ``` ### 2. Enum نصي ```typescript enum Status { Pending = "PENDING", Approved = "APPROVED", Rejected = "REJECTED", } let status: Status = Status.Approved; console.log(status); // "APPROVED" ``` ### 3. Enum مخصص ```typescript enum HttpStatus { OK = 200, NotFound = 404, ServerError = 500, } console.log(HttpStatus.OK); // 200 ``` ## Type Aliases — أسماء بديلة للأنواع يمكنك إعطاء اسم لنوع معقد لاستخدامه لاحقاً. ```typescript type UserId = string | number; type Point = { x: number; y: number }; type Callback = (data: string) => void; let id: UserId = "ABC123"; let point: Point = { x: 10, y: 20 }; ``` **الفرق بين `type` و `interface`:** - `type` أكثر مرونة (يمكن استخدامه مع Union, Tuple, ...). - `interface` أفضل للتوسيع (extends). ## تمارين عملية ### تمرين 1: الأنواع الأساسية عرّف متغيرات بالأنواع التالية: - `string`, `number`, `boolean`, `null`, `undefined` **الحل:** ```typescript let name: string = "أحمد"; let age: number = 25; let isStudent: boolean = true; let nothing: null = null; let notDefined: undefined = undefined; ``` ### تمرين 2: المصفوفات أنشئ مصفوفة أرقام ومصفوفة نصوص. **الحل:** ```typescript let numbers: number[] = [1, 2, 3, 4, 5]; let names: string[] = ["أحمد", "محمد", "علي"]; ``` ### تمرين 3: Tuple أنشئ Tuple يمثل معلومات كتاب: `[title, author, year]`. **الحل:** ```typescript let book: [string, string, number] = ["تعلم TypeScript", "أحمد", 2026]; console.log(book[0]); // تعلم TypeScript console.log(book[1]); // أحمد console.log(book[2]); // 2026 ``` ### تمرين 4: Union Types اكتب دالة تأخذ `string | number`، وترجع طوله/عدد أرقامه. **الحل:** ```typescript function getLength(value: string | number): number { if (typeof value === "string") { return value.length; } return value.toString().length; } console.log(getLength("أحمد")); // 4 console.log(getLength(12345)); // 5 ``` ### تمرين 5: Literal Types عرّف نوعاً يقبل فقط الأيام: `"saturday" | "sunday" | ...`. **الحل:** ```typescript type Day = "saturday" | "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday"; let today: Day = "monday"; console.log(today); ``` ### تمرين 6: Enum عرّف Enum يمثل حالات الطلب. **الحل:** ```typescript enum OrderStatus { Pending = "PENDING", Processing = "PROCESSING", Shipped = "SHIPPED", Delivered = "DELIVERED", Cancelled = "CANCELLED", } let order: OrderStatus = OrderStatus.Pending; console.log(order); // PENDING ``` ### تمرين 7: Type Alias عرّف `type` يمثل مستخدم، واستخدمه. **الحل:** ```typescript type User = { id: number; name: string; email: string; isActive: boolean; }; const user: User = { id: 1, name: "أحمد", email: "ahmed@example.com", isActive: true, }; ``` ### تمرين 8: Intersection Types ادمج نوعين في نوع واحد. **الحل:** ```typescript type HasName = { name: string }; type HasAge = { age: number }; type Person = HasName & HasAge; const person: Person = { name: "أحمد", age: 25, }; ``` ## حل المشاكل الشائعة ### 🔴 المشكلة 1: `Type 'X' is not assignable to type 'Y'` **السبب:** قيمة بنوع مختلف عن المعلن. ```typescript let age: number = "25"; // ❌ ``` **الحل:** ```typescript let age: number = 25; // ✅ let ageStr: string = "25"; // ✅ ``` ### 🔴 المشكلة 2: `Object is possibly 'null' or 'undefined'` **السبب:** TypeScript تحذرك من قيمة قد تكون فارغة. ```typescript function greet(name: string | null) { console.log(name.toUpperCase()); // ❌ } ``` **الحل:** ```typescript function greet(name: string | null) { if (name !== null) { console.log(name.toUpperCase()); // ✅ } } // أو باستخدام optional chaining: function greet2(name: string | null) { console.log(name?.toUpperCase()); // ✅ } ``` ### 🔴 المشكلة 3: `Property 'X' does not exist on type 'Y'` **السبب:** الوصول لخاصية غير موجودة. ```typescript let person = { name: "أحمد" }; console.log(person.age); // ❌ ``` **الحل:** أضف الخاصية للنوع: ```typescript let person: { name: string; age?: number } = { name: "أحمد" }; console.log(person.age); // ✅ ``` ### 🔴 المشكلة 4: `Type 'string' is not assignable to type 'number'` **السبب:** خلط بين الأنواع. **الحل:** تأكد من تطابق الأنواع، أو استخدم Union: ```typescript let value: string | number = "نص"; value = 25; // ✅ ``` ## جدول الأنواع الأساسية <table> <thead> <tr> <th>النوع</th> <th>الوصف</th> <th>مثال</th> </tr> </thead> <tbody> <tr> <td><code>string</code></td> <td>نصوص</td> <td><code>"أحمد"</code></td> </tr> <tr> <td><code>number</code></td> <td>أرقام</td> <td><code>25</code>, <code>99.99</code></td> </tr> <tr> <td><code>boolean</code></td> <td>منطقي</td> <td><code>true</code>, <code>false</code></td> </tr> <tr> <td><code>null</code></td> <td>فارغ</td> <td><code>null</code></td> </tr> <tr> <td><code>undefined</code></td> <td>غير معرف</td> <td><code>undefined</code></td> </tr> <tr> <td><code>any</code></td> <td>أي نوع (تجنبه)</td> <td><code>let x: any</code></td> </tr> <tr> <td><code>unknown</code></td> <td>غير معروف (آمن)</td> <td><code>let x: unknown</code></td> </tr> <tr> <td><code>void</code></td> <td>لا قيمة</td> <td><code>function f(): void</code></td> </tr> <tr> <td><code>never</code></td> <td>لا يحدث</td> <td><code>function f(): never</code></td> </tr> <tr> <td><code>array</code></td> <td>مصفوفة</td> <td><code>number[]</code></td> </tr> <tr> <td><code>tuple</code></td> <td>مصفوفة ثابتة</td> <td><code>[string, number]</code></td> </tr> <tr> <td><code>enum</code></td> <td>تعداد</td> <td><code>enum Color</code></td> </tr> <tr> <td><code>union</code></td> <td>اتحاد</td> <td><code>string | number</code></td> </tr> <tr> <td><code>intersection</code></td> <td>تقاطع</td> <td><code>A & B</code></td> </tr> </tbody> </table> ## قائمة تحقق نهائية <table> <thead> <tr> <th>المهمة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>فهم الأنواع البدائية</td> <td>⬜</td> </tr> <tr> <td>استخدام المصفوفات و Tuples</td> <td>⬜</td> </tr> <tr> <td>تعريف الكائنات بأنواع</td> <td>⬜</td> </tr> <tr> <td>فهم any, unknown, void, never</td> <td>⬜</td> </tr> <tr> <td>استخدام Union Types</td> <td>⬜</td> </tr> <tr> <td>استخدام Literal Types</td> <td>⬜</td> </tr> <tr> <td>تعريف Enums</td> <td>⬜</td> </tr> <tr> <td>استخدام Type Aliases</td> <td>⬜</td> </tr> <tr> <td>حل التمارين الثمانية</td> <td>⬜</td> </tr> </tbody> </table> ## ماذا بعد هذا المقال؟ الآن بعد أن أتقنت الأنواع الأساسية، أنت جاهز للمقال التالي: 1. **الواجهات (Interfaces)** — تعريف هياكل البيانات. 2. **الدوال مع الأنواع** — تعمق في أنواع الدوال. 3. **الفئات (Classes)** — البرمجة كائنية التوجه. ## الخلاصة في هذا المقال، تعلمت: - ✅ ما هو نظام الأنواع ولماذا نحتاجه. - ✅ الأنواع البدائية: string, number, boolean, null, undefined, bigint, symbol. - ✅ المصفوفات و Tuples. - ✅ الكائنات مع الأنواع. - ✅ الأنواع الخاصة: any, unknown, void, never. - ✅ Union Types و Intersection Types. - ✅ Literal Types. - ✅ Enums. - ✅ Type Aliases. **تذكر:** نظام الأنواع هو ما يجعل TypeScript قوية. كلما أتقنته، كلما أصبح كودك أكثر أماناً. **هل أتقنت الأنواع؟ شاركنا في التعليقات!**