Constraint (extends) va default type parametr

~20 daq · TypeScript · Generics

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])