Promise<T> الأنواع غير المتزامنة
آخر تحديث: 2026-10-22
Promise<T> الأنواع غير المتزامنة
تدور الأنواع غير المتزامنة حول Promise<T>: فنوع إرجاع الدالة async يُغلَّف تلقائيًا بطبقة Promise، بينما يفك await ذلك على مستوى القيم؛ ويقوم نوع الأداة Awaited<T> بالعمل نفسه على مستوى الأنواع (يفك الـ Promise المتداخلة إلى أقصاها). وحالما تفهم «ما النوع المحمول داخل الـ Promise» صار لكل متغير في الشيفرة غير المتزامنة نوع دقيق.
| المجموعة | الإعداد والتطبيق |
|---|---|
| النوع | بناء الجملة |
| الوضع الصارم | غير مطلوب |
ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.
📝 الصيغة
// الدوال async: نوع القيمة المُعادة يُلف دائمًا بـ Promise<T>
async function fetchUser(id: number): Promise<User> {
const res = await getJson("/users/" + id); // await يفكّ طبقة من الـ Promise
return res; // القيمة المُعادة هي User
}
// Awaited<T>: await على مستوى الأنواع
type A = Awaited<Promise<User>>; // User
type B = Awaited<Promise<Promise<User>>>; // User — حتى المتداخلة تُفكّ إلى النهاية
⚙️ المعاملات
| Promise<T> | حاوية عامة مدمجة؛ T هو نوع القيمة التي ستحصل عليها في نهاية الأمر. وتعمل مع async/await من دون أي استيراد |
|---|---|
| async | مُعدِّل دوال: يسمح باستخدام await داخل المتن؛ ويُغلَّف قيمة الإرجاع تلقائيًا بـ Promise — فالقيمة العادية T تصبح Promise<T> وما كان Promise أصلًا لا يُغلَّف مرتين |
| Awaited<T> | نوع أداة مدمج يحاكي الأثر النوعي لـ await: يفك Promise ليعطي T، ويفك التداخل تكراريًا، ويمرر الأنواع غير الـ Promise دون تغيير |
القيمة المُعادة:نوع إرجاع الدالة async هو Promise<T>: فسواء أعاد متن الدالة قيمة عادية T أو Promise<T> فالنوع النهائي Promise<T> (ولن يظهر أبدًا Promise<Promise<T>>).
▶ مثال
عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:
الناتج:
{"id":7,"title":"Write TypeScript notes","done":false}
todo#7 title="Write TypeScript notes" done=false
(مخرجات التشغيل بعد الترجمة؛ يُستنتج todo بوصفه Todo عبر await — فمن دونه تحصل على Promise<Todo> والوصول المباشر إلى todo.id خطأ نوعي)
💡 نقاط مهمة
ℹ️ معلومة داخل دالة async تتعادل الصيغتان return T وreturn Promise<T> تمامًا ولن يتكدس النوع إلى Promise<Promise<T>> — والـ Awaited<T> هي القاعدة ذاتها وقد تحولت إلى نوع أداة.
💡 تلميح نوع نتيجة Promise.all صف (tuple): فالصيغة Promise.all([p1, p2]) نوعها Promise<[A, B]> مع الحفاظ على نوع كل موضع منفردًا — وawait واحدة تحصل على كل القيم مع أنواع دقيقة لكل منها.
⚠️ تنبيه الاستثناءات المرمية داخل دالة async لا تُرمى بشكل متزامن بل تتحول إلى Promise مرفوض (rejected): يجب لفّ await بـ try/catch أو تسلسل .catch() وإلا حصلت على unhandled rejection؛ ونوع الإرجاع Promise<T> بذاته لا يكشف «احتمال الفشل».
🏷️ الإعداد والتطبيق ذو صلة
💡 حالات ذات صلة
المزيد من الحالات قادم قريبًا.
📚 دروس ذات صلة
❓ أسئلة شائعة
س ماذا تفعل Awaited<T> ومتى أستخدمها؟
ج تحاكي await على مستوى الأنواع: تتحول Promise<T> إلى T وتفك الـ Promise المتداخلة كليًا وتمرر غيرها دون تغيير. نادرًا ما تستخدمها مباشرة — إنها تظهر غالبًا داخل تعريفات الأنواع المدمجة (كـ Promise.all وأنواع إرجاع دوال async) وعندما تحتاج أدواتك المخصصة إلى «فك Promise»، مثل Unwrap<T> = Awaited<T>.
س ماذا يحدث إذا نسيت await؟
ج تحصل على Promise<Todo> لا Todo: فالوصول إلى .id خطأ نوعي (أوضح تحت strictNullChecks)، وفي التشغيل فهو «مهمة لم تنته بعد». ولن ينفذ await عنك TypeScript — كلما رأيت نوع Promise اسأل نفسك: هل أحتاج await؟
س هل يجب كتابة Promise<T> صراحة لدوال async؟
ج لا — يشتق الاستنتاج Promise<T> من تعليمات return. والكتابة الصريحة تعود بالنفع في API العمومية (فالعقد مرئي وأخطاء التوقيع تظهر أولًا عند تعديل التنفيذ)؛ أما الدوال الداخلية الصغيرة فاتركها للاستنتاج.