TypeScript: قائمة TypeScript (enum)
آخر تحديث: 2026-08-26
تعد القوائم (Enums) إحدى ميزات أنواع TypeScript القليلة التي لها سلوك في وقت التشغيل — فهي تمثل نوعًا وتُنشئ كائنات JavaScript فعلية في الوقت نفسه.
1. الترقيم العددي
(1) قواعد النحو الأساسية
enum Direction {
Up, // 0(Auto-increment from 0)
Down, // 1
Left, // 2
Right // 3
}
let dir: Direction = Direction.Up;
console.log(dir); // 0
console.log(Direction[0]); // "Up"(Inverse Mapping)
(2) القيم الأولية المخصصة
enum Status {
Active = 1, // 1
Inactive, // 2(Auto-increment)
Pending // 3
}
enum HttpStatus {
OK = 200,
Moved = 301,
BadRequest = 400,
NotFound = 404,
ServerError = 500
}
let code: HttpStatus = HttpStatus.OK;
console.log(code); // 200
(3) التعيين العكسي للتعدادات العددية
بعد الترجمة، تُنشئ التعدادات الرقمية كائنات تعيين ثنائية الاتجاه — حيث يمكنك استرداد قيمة بناءً على اسمها، أو اسمًا بناءً على قيمته:
enum Role {
Admin = 0,
Editor = 1,
Viewer = 2
}
// Forward Mapping: name → value
console.log(Role.Admin); // 0
// Inverse Mapping: value → name
console.log(Role[0]); // "Admin"
console.log(Role[1]); // "Editor"
كود JavaScript الذي تم إنشاؤه بعد التحويل البرمجي:
var Role;
(function (Role) {
Role[Role["Admin"] = 0] = "Admin";
Role[Role["Editor"] = 1] = "Editor";
Role[Role["Viewer"] = 2] = "Viewer";
})(Role || (Role = {}));
2. تعداد السلاسل
(1) قواعد النحو الأساسية
يجب تعيين كل عنصر من عناصر التعداد التسلسلي بشكل صريح — فلا توجد زيادة تلقائية:
enum EventType {
Click = "click",
Change = "change",
Submit = "submit",
Focus = "focus"
}
let event: EventType = EventType.Click;
console.log(event); // "click"
(2) لا يوجد تعيين عكسي لتعداد السلاسل
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
console.log(Color.Red); // "RED" ✅ Forward Mapping
// console.log(Color["RED"]); // undefined ❌ String enumeration has no reverse mapping
▶ مثال: تحديد حالات الطلبات باستخدام قائمة التعداد
enum OrderStatus {
Pending = "PENDING",
Processing = "PROCESSING",
Shipped = "SHIPPED",
Delivered = "DELIVERED",
Cancelled = "CANCELLED"
}
function getStatusLabel(status: OrderStatus): string {
switch (status) {
case OrderStatus.Pending: return "Pending";
case OrderStatus.Processing: return "Processing...";
case OrderStatus.Shipped: return "Shipped";
case OrderStatus.Delivered: return "Delivered";
case OrderStatus.Cancelled: return "Canceled";
}
}
let currentStatus: OrderStatus = OrderStatus.Processing;
console.log(`Current Status:${getStatusLabel(currentStatus)}`);
console.log(`Status Code:${currentStatus}`);
الناتج:
Current Status:Processing...
Status Code:PROCESSING
3. عمليات التعداد غير المتجانسة
يمكن أن تحتوي القوائم على مزيج من القيم الرقمية والسلسلات النصية — لكن لا يُنصح بذلك:
enum Mixed {
No = 0,
Yes = "YES"
}
4. التعدادات الثابتة
const enum يتم استبداله بتعبير مضمن أثناء التحويل البرمجي — ولا يُنشئ كائنًا في JavaScript، مما يوفر أداءً أفضل ولكن بوظائف محدودة:
(1) قواعد النحو الأساسية
const enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
let c = Color.Red;
// After compilation:let c = "RED"(Direct Inline Replacement,No enumeration objects)
(2) قيود عمليات التعداد في const
const enum Direction {
Up = "UP",
Down = "DOWN"
}
// ❌ const Enumerations cannot use reverse mapping.
// console.log(Direction[0]);
// ❌ const Enumerations cannot be iterated over at runtime
// for (let d in Direction) { }
// ✅ Only simple value references are allowed.
let dir = Direction.Up; // Compile to let dir = "UP"
(3) الخيار preserveConstEnums
إذا كنت تريد ألا يتم تضمين التعدادات الثابتة (const enumerations) بشكل مباشر، بل الاحتفاظ بكائنات التعداد، فقم بتمكين preserveConstEnums: true:
// tsconfig.json
// "preserveConstEnums": true
const enum Status {
Active = 1
}
let s = Status.Active;
// After compilation:Enumeration objects are still generated(But quotes are also inlined.)
5. وقت التشغيل وأمان الأنواع في قوائم التعداد
(1) التعدادات كأنواع
enum Role {
Admin,
Editor,
Viewer
}
function checkAccess(role: Role): boolean {
return role === Role.Admin || role === Role.Editor;
}
checkAccess(Role.Admin); // ✅
checkAccess(0); // ✅ Numeric enumerations accept numeric values(but ⚠️ not recommended)
// checkAccess(99); // ✅ Compilation successful!Any number can be converted to——This is a numeric enumeration vulnerability.
let r: Role = 99 هي قيمة صالحة. ويرجع ذلك إلى أن التعدادات العددية صُممت مع أخذ علامات البت في الاعتبار. إذا كنت بحاجة إلى قيود صارمة على القيم، فاستخدم التعدادات السلسلية أو أنواع الاتحاد الحرفية.
(2) يعد التعداد بالسلسلة أكثر أمانًا
enum Role {
Admin = "ADMIN",
Editor = "EDITOR",
Viewer = "VIEWER"
}
let r: Role = Role.Admin; // ✅
// r = "ADMIN"; // ❌ String enumeration does not accept regular strings.
// r = "SUPERADMIN"; // ❌ Only enumeration members are accepted
6. قوائم التعداد مقابل أنواع الاتحاد الحرفية
| الخاصية | التعداد | نوع الاتحاد الحرفي |
|---|---|---|
| كود وقت التشغيل | نعم (يتم إنشاء كائنات) | لا (أنواع بحتة) |
| التعيين العكسي | التعداد الرقمي: نعم | لا |
| تصفح جميع القيم | نعم | لا |
| قيود القيمة | التعداد العددي (أكثر مرونة) | صارم |
| تلميحات الكود | الإكمال التلقائي لعناصر قائمة التعداد | الإكمال التلقائي لقيم الاتحاد |
| حجم الحزمة | يزيد من حجم الكود | حجم صفر |
| التوافق مع JS | قيم التعداد هي كائنات مخصصة | سلاسل/أرقام أصلية |
(1) سيناريوهات استخدام القوائم التعدادية
- يلزم وجود تعيين عكسي (القيمة → الاسم)
- يجب تكرار جميع القيم أثناء وقت التشغيل
- يجب أن تكون قوائم التعداد جاهزة للاستخدام ككائنات في وقت التشغيل (مثل تعيينات الثوابت في واجهة برمجة التطبيقات)
(2) سيناريوهات تستخدم أنواع الاتحاد الحرفي (يُنصح بها كخيار أول)
- لا يُشترط سوى قيود النوع
- يتطلب قابلية التشغيل البيني مع سلاسل النصوص والأرقام الأصلية في JavaScript
- احرص على أن يكون حجم الحزمة أصغر ما يمكن
- لا يلزم وجود سلوك أثناء التشغيل
▶ مثال: مقارنة بين الطريقتين
// Method 1:Enumeration
enum Direction1 {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
// Method 2:Literal Union Types(Recommendations)
type Direction2 = "UP" | "DOWN" | "LEFT" | "RIGHT";
// The two are equivalent in terms of type constraints.
function move1(dir: Direction1): void { console.log(dir); }
function move2(dir: Direction2): void { console.log(dir); }
move1(Direction1.Up); // ✅ "UP"
move2("UP"); // ✅ Use the string directly,Even simpler
// But enumerations can be iterated over
console.log(Object.values(Direction1));
// ["UP", "DOWN", "LEFT", "RIGHT"]
// Literal union types cannot be iterated over(Pure compile-time types)
الناتج:
// Executed successfully
▶ مثال: التعدادات الثابتة لأمان الأنواع بدون تكلفة
const enum LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3
}
function log(level: LogLevel, message: string): void {
const prefix = ["DEBUG", "INFO", "WARN", "ERROR"][level];
console.log(`[${prefix}] ${message}`);
}
log(LogLevel.Info, "Server started"); // Compiles to: log(1, "Server started")
log(LogLevel.Error, "Connection lost"); // Compiles to: log(3, "Connection lost")
الناتج:
[INFO] Server started
[ERROR] Connection lost
const enum members are inlined at compile time—no enum object is emitted in the JS output, resulting in smaller bundle size.
❓ أسئلة شائعة
enum Perm { Read = 1, Write = 2, Execute = 4 })، وتعتبر تركيبات البتات Read | Write = 3 صالحة ولكنها غير مدرجة في تعريف التعداد. لذلك، خفف نوع التعداد الرقمي من قيوده. إذا كنت لا ترغب في هذا السلوك، فاستخدم التعدادات السلسلية أو أنواع الاتحاد الحرفية.const وقائمة التعداد العادية؟const في وقت التحويل البرمجي — حيث يتم استبدال Color.Red مباشرةً بـ "RED"، ولا يتم إنشاء أي كائن لقائمة التعداد. وتتمثل الميزة في حجم حزمة أصغر وأداء أسرع في وقت التشغيل؛ أما العيب فهو أنه لا يمكن إعادة تعيينها، ولا يمكن التكرار عليها، ولا يمكن استخدامها في سياقات ديناميكية. يُفضل استخدام التعدادات const (ما لم تكن بحاجة إلى ميزات وقت التشغيل).interface Config { role: Role }. كما يمكن استخدام عناصر قوائم التعداد كعناصر في أنواع الاتحاد—type Mixed = Role.Admin | "superadmin". وتُعد قوائم التعداد مفهومًا موحدًا للنوع والقيمة، مما يوفر مرونة في الاستخدام.📖 ملخص
- تتزايد التعدادات الرقمية تلقائيًا بدءًا من 0 وتدعم التعيين العكسي؛ أما التعدادات النصية فيجب تعيينها صراحةً ولا تدعم التعيين العكسي.
- لا يُنصح باستخدام عمليات التعداد غير المتجانسة (التي تجمع بين الأرقام والسلاسل النصية)
- يتم دمج التعدادات الثابتة (Const) في وقت التحويل البرمجي، مما يؤدي إلى عدم وجود أي عبء إضافي في وقت التشغيل، ولكن مع وظائف محدودة
- يمكن لأنواع التعداد الرقمية أن تقبل أي رقم (وهو عيب في التصميم)، في حين أن أنواع التعداد النصية أكثر تقييدًا
- في معظم الحالات، يُنصح باستخدام أنواع الاتحاد الحرفية بدلاً من القوائم التعدادية — فهي أخف وزنًا وأكثر أمانًا ولا تشغل أي مساحة.
- استخدم التعداد فقط عندما تحتاج إلى تعيين القيم في الاتجاه العكسي أو تكرار جميع القيم.
📝 تمارين
- المسألة الأساسية (الصعوبة ⭐): مع إعطاء سلسلة من القيم المُعددية
Season(الربيع/الصيف/الخريف/الشتاء)، اكتب دالة تُرجع وصفًا لنطاق الأشهر المقابل بناءً على الفصل. - تمرين متقدم (مستوى الصعوبة ⭐⭐): استخدم
const enumلتعريف طرق HTTP (GET/POST/PUT/DELETE)، ثم قم بتعريف واجهةRequestتتضمن الخصائصmethodوurl. أنشئ عدة كائنات طلب للتحقق من قيود الأنواع. - التحدي (الصعوبة: ⭐⭐⭐): استخدم أنواع الاتحاد الحرفي بدلاً من القوائم التعدادية لتنفيذ «نظام الأذونات»: عرّف
Permission = "read" | "write" | "execute" | "admin"، ثم قم بتنفيذ الدالةhasPermission(userPerms: Permission[], required: Permission): booleanللتحقق مما إذا كان المستخدم يمتلك إذنًا معينًا (يمتلك «admin» جميع الأذونات).