Menu
flag Ar iconالعربيةdown icon

Pick في TypeScript: اختيار خصائص من نوع (أمثلة)

Pick<T, K> ينشئ نوعًا فيه خصائص T التي مفاتيحها في K فقط. تعرّف على Pick بمفتاح واحد أو عدة مفاتيح، وكيف يفحص المفاتيح، والفرق بين Pick وOmit، والاختيار من أنواع متداخلة، ودالة pick() بأنواع صحيحة، واختيار الخصائص حسب نوع قيمتها.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

Pick<T, K> نوع أداة مدمج ينشئ نوع كائن لا يحتوي إلا خصائص T المذكورة في K. استخدمه عندما تحتاج دالة أو مكوّن إلى بضعة حقول من نوع أكبر:

تقبل renderPreview كائن User كاملًا وتقبل أيضًا كائنًا بسيطًا { id, name }، لأنها لا تطلب إلا ما تستخدمه. وهذا يسهّل استدعاءها واختبارها. Pick خاص بالأنواع فقط: ما زال كائن ada الكامل يملك خصائصه الخمس وقت التشغيل.

الصياغة وفحص المفاتيح

Pick<Type, Keys>

Keys مفتاح واحد أو union من المفاتيح، ويجب أن يكون كل منها موجودًا في Type. والتعريف في المكتبة القياسية لـ TypeScript يجعل ذلك قيدًا:

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

بسبب K extends keyof T يكون المفتاح المكتوب خطأً أو المفقود خطأ ترجمة، ويستطيع محررك إكمال أسماء المفاتيح تلقائيًا:

الخطأ هو error TS2344: Type '"cost"' does not satisfy the constraint 'keyof Product'. وهذا فرق عن Omit الذي لا تُفحص مفاتيحه.

Pick يحافظ على readonly والخصائص الاختيارية

يمر Pick على مفاتيح T، فتحتفظ كل خاصية مختارة بمُعدِّلاتها:

يُظهر السطر الأخير { id: 8 } لأن readonly فحص وقت الترجمة فقط: بُلّغ عن الإسناد، ثم كُتم بـ @ts-expect-error، ومع ذلك نُفّذ. لتغيير المُعدِّلات أثناء الاختيار، غلّف النتيجة: Partial<Pick<Account, "plan">> أو Required<Pick<Account, "email">>.

Pick أم Omit

يسمّي Pick ما يُبقى؛ ويسمّي Omit ما يُحذف. كلاهما يعطي النتيجة نفسها اليوم، لكنهما يتصرفان بشكل مختلف عندما يكبر النوع المصدر:

Pick<T, K>Omit<T, K>
ما تذكرهالمفاتيح التي تُبقىالمفاتيح التي تُحذف
الخصائص الجديدة في Tلا تُضمتُضم تلقائيًا
مفتاح مجهول في Kخطأ ترجمة (TS2344)يُقبل بصمت
مناسب لـاستجابات API والعروض العامة والـ props«كل شيء عدا السر»

للبيانات التي تغادر خادمك، Pick هو الخيار الافتراضي الأكثر أمانًا: لا يظهر شيء في النوع ما لم يضفه أحد عن قصد.

الاختيار من أنواع متداخلة

لا يرى Pick إلا مفاتيح المستوى الأعلى: المسار المنقّط مثل Pick<Customer, "address.city"> خطأ (TS2344)، وليس اختيارًا متداخلًا. استخدم indexed access type للوصول إلى النوع المتداخل، ثم اختر منه:

Customer["address"] هو نوع الخاصية address. والصياغة نفسها تصل إلى عناصر المصفوفات: لخاصية orders: Order[] يكون Customer["orders"][number] هو Order.

دالة pick() بأنواع صحيحة

لا يفعل Pick شيئًا وقت التشغيل. دالة generic صغيرة تنسخ الخصائص المختارة إلى كائن جديد وتعيد Pick<T, K> بالضبط:

يسمح K extends keyof T لـ TypeScript باستنتاج K من الوسائط النصية، فيكون لنوع القيمة المُعادة المفاتيح المختارة بالضبط. تأكيد النوع {} as Pick<T, K> ضروري لأن الكائن الفارغ لا يملك تلك الخصائص بعد؛ والحلقة تملؤها.

اختيار الخصائص حسب نوع قيمتها

يختار Pick حسب اسم المفتاح. للاختيار حسب نوع الخاصية، مثل «كل الحقول النصية»، اكتب mapped type مع مرشّح للمفاتيح:

تحوّل جملة as كل مفتاح إلى نفسه عندما يطابق نوعه، وإلى never في غير ذلك، والمفاتيح never تُسقط. وهناك دقة واحدة: نوع الخاصية الاختيارية يتضمن undefined، لذا فالخاصية الاختيارية subtitle?: string لن تُحسب هنا من النوع string؛ اختبر مقابل string | undefined لتضمها.

الأسئلة الشائعة

ماذا يفعل Pick في TypeScript؟

يبني Pick<T, K> نوع كائن لا يحتوي إلا خصائص T التي مفاتيحها في K. فـ Pick<User, "id" | "name"> هو { id: number; name: string } عندما يملك User هاتين الخاصيتين إضافة إلى غيرهما. يعمل على الأنواع فقط ولا يحذف شيئًا من الكائنات وقت التشغيل.

ما الفرق بين Pick وOmit؟

يذكر Pick الخصائص التي تُبقى، ويذكر Omit الخصائص التي تُحذف. عندما يكتسب النوع المصدر خاصية جديدة، يضمها Omit تلقائيًا ولا يضمها Pick. ويتحقق Pick أيضًا من وجود مفاتيحه في النوع؛ أما Omit فيقبل أي مفتاح.

كيف أختار عدة خصائص في TypeScript؟

مرّر union من المفاتيح: Pick<User, "id" | "name" | "email">. يجب أن تكون كل المفاتيح موجودة في User، وإلا يبلّغ المترجم الخطأ TS2344.

كيف أختار خاصية متداخلة في TypeScript؟

لا يختار Pick إلا خصائص المستوى الأعلى. للوصول إلى نوع متداخل استخدم indexed access type ثم اختر منه: Pick<User["address"], "city">. وللحفاظ على التداخل اجمع بينهما: Pick<User, "id"> & { address: Pick<User["address"], "city"> }.

هل يحافظ Pick على المُعدِّلين readonly والاختياري؟

نعم. Pick نوع mapped type يمر على مفاتيح T، فالخاصية التي هي readonly أو اختيارية في T تبقى كذلك في النوع الناتج.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن