Constraint (extends) va default type parametr
Generic funksiya yozdingiz — lekin T istalgan tur bo'lishi mumkin, ba'zi xususiyatlarga yetishish qiyin:
function uzunlik<T>(x: T): number {
return x.length; // ❌ — T da .length bo'lmasligi mumkin
}
Constraint — T extends SomeTur bilan T faqat ma'lum shaklda bo'lishini talab qilish.
extends — constraint
function uzunlik<T extends { length: number }>(x: T): number {
return x.length; // ✅ — T da .length kafolatlanган
}
uzunlik("salom"); // ✅ — string.length bor
uzunlik([1, 2, 3]); // ✅ — array.length bor
uzunlik(42); // ❌ — number da .length yo'q
keyof bilan constraint
Ob'ektdan faqat mavjud kalitlarni olish:
function olish<T, K extends keyof T>(ob: T, kalit: K): T[K] {
return ob[kalit];
}
const user = { ism: "Ali", yosh: 25, email: "ali@mail.com" };
olish(user, "ism"); // string ✅
olish(user, "yosh"); // number ✅
olish(user, "bio"); // ❌ — 'bio' keyof typeof user emas
Interface constraint
interface Uzunlikli {
length: number;
}
function birinchiElementlar<T extends Uzunlikli>(
massiv: T,
soni: number
): T {
// T da .length bor deb kafolatlanган
console.log(massiv.length);
return massiv;
}
Default tur parametr
Generic parametrga standart tur berish — ko'rsatilmasa shu ishlatiladi:
interface ApiJavob<T = unknown> {
data: T;
status: number;
}
// T ko'rsatilmasa — unknown
const j1: ApiJavob = { data: "...", status: 200 };
// j1.data: unknown
// T ko'rsatilsa — shu ishlatiladi
const j2: ApiJavob<string> = { data: "Ali", status: 200 };
// j2.data: string
Default va constraint birga
function yaratish<T extends object = Record<string, unknown>>(
qiymat?: T
): T {
return qiymat ?? ({} as T);
}
yaratish(); // Record<string, unknown>
yaratish({ ism: "Ali" }); // { ism: string }
yaratish("matn"); // ❌ — string extends object emas
Amaliy — mutable/immutable
type Mutable<T extends object> = {
-readonly [K in keyof T]: T[K];
};
interface Config {
readonly host: string;
readonly port: number;
}
type MutableConfig = Mutable<Config>;
// { host: string; port: number } — readonly olib tashlandi
Tez-tez uchraydigan xatolar
Constraint etarli emas:
function saralash<T>(massiv: T[]): T[] {
return massiv.sort((a, b) => a - b);
// ❌ — T da arifmetik operator bo'lmasligi mumkin
}
function saralash<T extends number>(massiv: T[]): T[] {
return massiv.sort((a, b) => a - b); // ✅
}
Xulosa
// Constraint
function fn<T extends { length: number }>(x: T): number { return x.length; }
function fn<T, K extends keyof T>(o: T, k: K): T[K] { return o[k]; }
// Default tur
interface Box<T = unknown> { qiymat: T; }
const b1: Box = { qiymat: "..." }; // unknown
const b2: Box<string> = { qiymat: "..." }; // string
// Birga
function fn<T extends object = Record<string, string>>(x?: T): T { ... }
Keyingi dars
37-dars: keyof, typeof operatorlari va lookup types (T[K])