افهم كيف تُحافظ الأنواع المُعيَّنة التماثلية على المُعدِّلات، وكيف تُعيد جملة as تسمية المفاتيح أو تُرشِّحها.
افتح هذا الدرس في Kodokonالنوع المُعيَّن يتكرّر على مجموعة من المفاتيح لإنتاج نوع كائن جديد. تُسمّى الصيغة [K in keyof T] تماثلية (homomorphic): يعرف المُصرِّف أن البنية آتية من T، فينسخ تلقائياً مُعدِّلَي readonly و? لكل خاصّية أصلية. وتتيح البادئتان + و- إضافة هذه المُعدِّلات أو إزالتها صراحة: هذه هي بالضبط الآلية الداخلية خلف Partial وRequired وReadonly.
type Mutable<T> = {
-readonly [K in keyof T]-?: T[K];
};
interface Config {
readonly host?: string;
readonly port?: number;
}
type Draft = Mutable<Config>;
// { host: string; port: number }منذ TypeScript 4.1، تُتيح جملة as إعادة تعيين المفاتيح: يمكن إعادة تسمية كل مفتاح فوراً، عادةً عبر نوع سلسلة قالبية. وإذا أنتجت الجملة never، فإن المفتاح يُزال ببساطة من النتيجة: هذه هي آلية ترشيح الخصائص الرسمية. لاحظ & string في المثال: قد يحتوي keyof T على مفاتيح من نوع symbol أو number، وهي غير متوافقة مع سلسلة قالبية.
type Getters<T> = {
[K in keyof T & string as `get${Capitalize<K>}`]:
() => T[K];
};
interface User { name: string; age: number }
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }
type OnlyMethods<T> = {
[K in keyof T as
T[K] extends (...args: never[]) => unknown
? K : never]: T[K];
};دقّة في المواصفات كثيراً ما يجري تجاهلها: عند تطبيقه على مصفوفة أو صف tuple، لا يُنتج النوع المُعيَّن التماثلي كائناً بالمفاتيح 0 و1 وlength. يُحافظ المُصرِّف على طبيعة النوع: فيُحوِّل العناصر ويُبقي شكل المصفوفة أو الصف tuple. هذا ما يسمح لـReadonly<[number, string]> بأن يبقى صف tuple. ويختفي هذا الحفظ فور أن يتوقّف النوع المُعيَّن عن كونه تماثلياً، مثلاً مع [P in K] حيث K اتّحاد اعتباطي من المفاتيح.
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
type Pair = Immutable<[number, string]>;
// readonly [number, string]: the tuple survives
type List = Immutable<string[]>;
// readonly string[]as القيمة never لمفتاح؟{ readonly [K in keyof T]: T[K] } عند تطبيقه على الصف tuple [number, string]؟-? في نوع مُعيَّن؟