تقيّد مُعاملات أنواعك بـextends وتوفّر قيما افتراضية لبناء واجهات برمجية عامة مريحة.
افتح هذا الدرس في Kodokonالنوع العام غير المقيّد معتم: داخل جسم الدالة، T لا يسمح لك بفعل أي شيء. جملة extends تُنشئ عقدا أدنى على مُعامل النوع، فتفتح الوصول إلى الخصائص المضمونة مع الحفاظ على النوع الدقيق للمُنادي. هذا هو الفرق الجوهري عن مُعامل مُنوَّع بواجهة: القيد يحفظ المعلومة، والواجهة تمحوها.
function longest<T extends { length: number }>(
a: T,
b: T
): T {
return a.length >= b.length ? a : b;
}
const word = longest("hello", "worldwide");
const list = longest([1, 2], [3, 4, 5]);ثنائي K extends keyof T هو النمط الأكثر ربحية في الاستعمال اليومي: يربط مُعاملَي نوع معا ويضمن استاتيكيا أن المفتاح ينتمي فعلا إلى الكائن. نوع العائد T[K] (وهو نوع وصول مُفهرَس) يتتبّع بدقة الخاصية المطلوبة. هكذا بالضبط تُنوَّع دوال مثل pick أو pluck من مكتبات الأدوات.
function getProp<T extends object, K extends keyof T>(
obj: T,
key: K
): T[K] {
return obj[key];
}
const config = { port: 8080, host: "localhost" };
const port = getProp(config, "port");
const host = getProp(config, "host");القيم الافتراضية (T = string) تجعل النوع العام اختياريا عند موضع النداء: لا يقدّم المستعملون وسيط النوع إلا حين يريدون الخروج عن الحالة الشائعة. وباجتماعها مع قيد (T extends X = Y)، تُحدّد الحدّ والسلوك الضمني معا. يجب أن تُحقّق القيمة الافتراضية القيدَ، وإلا فإن التصريح نفسه لا يُصرَّف. هذا هو النمط المعياري لعملاء HTTP والمخازن ومُصدِرات الأحداث المُنوَّعة.
interface ApiResponse<T = unknown> {
status: number;
data: T;
}
async function fetchJson<T = unknown>(
url: string
): Promise<ApiResponse<T>> {
const res = await fetch(url);
return { status: res.status, data: await res.json() };
}
interface Post { id: number; title: string }
const typed = await fetchJson<Post>("/api/posts/1");
const loose = await fetchJson("/api/health");K extends keyof T في توقيع عام؟longest<T extends { length: number }> على longest(a: { length: number }, b: ...) بلا أنواع عامة؟<T = unknown> على <T = any> قيمة افتراضية؟