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

أنواع الوصول المفهرس في TypeScript: T[K] وT[number]

نوع الوصول المفهرس (indexed access type) يقرأ نوع خاصية من نوع آخر: Person["age"] هو number. تعرّف على T["key"]، ومفاتيح الـ union، وT[keyof T]، وT[number] لعناصر المصفوفات، وفهارس الـ tuples، و(typeof arr)[number] لتحويل مصفوفة const إلى union.

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

نوع الوصول المفهرس يبحث عن نوع خاصية في نوع آخر، بصيغة الأقواس المربعة نفسها التي تستخدمها JavaScript للوصول إلى الخصائص. Person["age"] هو number، وPerson["address"]["city"] هو string.

الفائدة مصدر واحد للحقيقة. Age ليس نسخة ثانية من number: إن تغيّر Person["age"] إلى string يتغير معه كل نوع مكتوب بصيغة Person["age"]. أنواع الوصول المفهرس تعمل وقت الترجمة فقط؛ ولا تولّد أي JavaScript.

مفاتيح الـ Union وT[keyof T]

يمكن أن يكون الفهرس union من المفاتيح. وتكون النتيجة union أنواع الخصائص:

Product[keyof Product] هو طريقة التعبير على مستوى الأنواع عن «أي قيمة خاصية في Product». وطلب مفتاح غير موجود خطأ ترجمة: Product["price"] يعطي error TS2339: Property 'price' does not exist on type 'Product'.

الخصائص الاختيارية تتضمن undefined

مع strictNullChecks (المفعّل ضمن strict) يتضمن نوع الخاصية الاختيارية undefined، وكذلك نوع الوصول المفهرس إليها:

type Profile = { name: string; nickname?: string };

type Nick = Profile["nickname"]; // string | undefined

لحذف undefined غلّفه: NonNullable<Profile["nickname"]> هو string.

أنواع عناصر المصفوفات بـ T[number]

تُفهرس المصفوفات بالأرقام، ففهرسة نوع مصفوفة بـ number تعطي نوع العنصر. ويعمل ذلك أيضًا عبر عدة مستويات:

هذا مفيد حين يأتي نوع من مكان لا تتحكم فيه، مثل عميل API مولَّد: يسمّي ApiResponse["data"]["users"][number] نوع المستخدم دون أن يكون أحد قد صدّره.

الـ Tuples: الفهرسة بالموضع

يمكن فهرسة نوع tuple بموضع محدد، وبـ number للحصول على union أنواع كل العناصر، وبـ "length" للحصول على طوله كنوع حرفي:

(typeof arr)[number]: نوع Union من مصفوفة const

أشيع استخدام عملي: احتفظ بقائمة القيم المسموحة كمصفوفة (لتتمكن من المرور عليها وقت التشغيل) واشتق نوع الـ union منها (ليفحصه المترجم).

جزءان يجعلان ذلك ممكنًا. تجعل as const المصفوفة tuple للقراءة فقط من أنواع حرفية؛ ودونها يكون ROLES من النوع string[] ويكون (typeof ROLES)[number] مجرد string. ثم يحوّل typeof القيمة إلى نوع، ويجمع [number] عناصرها في union. الأقواس اختيارية (typeof ROLES[number] يعني الشيء نفسه)، لكنها توضح ترتيب العمليات.

فحص نص مقابل المصفوفة

لهذا الـ tuple للقراءة فقط مفاجأة واحدة. التابع includes فيه لا يقبل إلا نوع العنصر، فلا يمكنك تمرير نص عشوائي إليه:

index.ts(6,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"admin" | "editor" | "viewer"'.

وسّع المصفوفة إلى readonly string[] لأجل الفحص، وحوّل الدالة إلى type guard كي يضيّق الفحص الناجح القيمة:

يعطيك هذا النمط قائمة واحدة للمهمتين: يستخدم الفحص وقت التشغيل المصفوفة، والنوع مشتق منها، فلا يمكن أن يتباعدا.

الوصول المفهرس في الـ Generics: T[K]

داخل generic يكون T[K] مع K extends keyof T هو نوع الخاصية التي اختارها المستدعي أيًا كانت:

function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
  return items.map((item) => item[key]);
}

const users = [
  { name: "Ada", age: 36 },
  { name: "Linus", age: 28 },
];

const names = pluck(users, "name"); // string[]
const ages = pluck(users, "age");   // number[]

القيد K extends keyof T هو ما يجعل T[K] صالحًا. دونه لا تستطيع TypeScript أن تعرف أن K مفتاح في T، فتبلّغ error TS2536: Type 'K' cannot be used to index type 'T'.

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

المكتوبالمعنىمثال على النتيجة
T["key"]نوع خاصية واحدةPerson["age"] هو number
T["a" | "b"]union أنواع تلك الخصائصstring | number
T[keyof T]union أنواع كل الخصائصنوع كل قيمة
T["a"]["b"]خاصية متداخلةPerson["address"]["city"]
Arr[number]نوع عنصر المصفوفةUser[] يعطي User
Tup[0]عنصر الـ tuple في موضع معيننوع العنصر الأول
Tup["length"]طول الـ tuple كقيمة حرفية3
(typeof arr)[number]union قيم مصفوفة const"admin" | "editor"
T[typeof key]الفهرسة بنوع ثابتمثل T["name"]

الفهرس نوع دائمًا. يفشل Person[key] حيث key متغير const بخطأين: error TS2538: Type 'key' cannot be used as an index type. وerror TS2749: 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?.

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

ما هو نوع الوصول المفهرس في TypeScript؟

نوع يُكتب T[K] ويبحث عن نوع الخاصية K في النوع T. مع type Person = { name: string; age: number } يكون Person["age"] هو number. يستخدم صيغة الأقواس المربعة نفسها المستخدمة للوصول إلى الخصائص في JavaScript، لكنه يعمل على الأنواع وقت الترجمة.

كيف أحصل على نوع عناصر مصفوفة في TypeScript؟

فهرس نوع المصفوفة بـ number: للنوع type Users = User[] يكون Users[number] هو User. ولقيمة مصفوفة، اجمعه مع typeof: (typeof users)[number].

كيف أحوّل مصفوفة نصوص إلى نوع union؟

عرّف المصفوفة بـ as const لتحتفظ TypeScript بالقيم الحرفية، ثم فهرسها بـ number: const roles = ["admin", "editor"] as const; type Role = (typeof roles)[number]; يعطي "admin" | "editor". دون as const يكون نوع العنصر مجرد string.

لماذا لا أستطيع استخدام متغير فهرسًا في نوع وصول مفهرس؟

يجب أن يكون الفهرس نوعًا. يفشل Person[key] مع const key = "name" (الخطآن TS2538 وTS2749) لأن key قيمة. اكتب Person[typeof key]، أو استخدم القيمة الحرفية مباشرة: Person["name"].

ماذا تعني T[keyof T]؟

تفهرس T بـ union كل مفاتيحه، فتكون النتيجة union كل أنواع خصائصه. للنوع { a: string; b: number } تكون string | number. إنها طريقة التعبير على مستوى الأنواع عن «أي قيمة في هذا الكائن».

Coddy programming languages illustration

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

ابدأ الآن