Generics nima uchun kerak? — muammo va yechim

~20 daq · TypeScript · Generics

Massivning birinchi elementini qaytaruvchi funksiya yozildi:

function birinchi(arr: number[]): number {
  return arr[0];
}

Stringlar massivi uchun ham kerak bo'ldi — yana bir funksiya:

function birinchiString(arr: string[]): string {
  return arr[0];
}

Ob'ektlar uchun yana bitta. Mantiq bir xil — faqat tur boshqacha. Generics — tur o'zgaruvchisi, mantiqni qayta yozmasdan istalgan tur bilan ishlash.


any bilan yechim — noto'g'ri

function birinchi(arr: any[]): any {
  return arr[0];
}

const son    = birinchi([1, 2, 3]);    // any — number emas
const matn   = birinchi(["a", "b"]);  // any — string emas
son.toFixed(); // TypeScript ruxsat beradi — lekin son any bo'lishi mumkin

any bilan tur yo'qoladi — TypeScript tekshiruvini o'chiradi.


Generic — tur parametri <T>

function birinchi<T>(arr: T[]): T {
  return arr[0];
}

T — tur parametri (placeholder). Chaqirilganda TypeScript T ni aniqlab oladi:

const son  = birinchi([1, 2, 3]);    // T=number → number
const matn = birinchi(["a", "b"]);   // T=string → string
const user = birinchi([{ism: "Ali"}]); // T={ism:string} → {ism:string}

son.toFixed();  // ✅ number metodi
matn.toUpperCase(); // ✅ string metodi

Generic qanday ishlaydi

birinchi([1, 2, 3]) chaqirilganda:
  arr: number[]  →  T = number  deb aniqlanadi
  qaytish turi:    T = number

birinchi(["a", "b"]) chaqirilganda:
  arr: string[]  →  T = string
  qaytish turi:    T = string

TypeScript T ni chaqirilishdan avtomatik aniqlaydi — annotatsiya shart emas.


Aniq ko'rsatish ham mumkin

const son = birinchi<number>([1, 2, 3]);
// T ni aniq belgilash — lekin odatda shart emas

Yana bir misol — identity funksiya

function qaytarish<T>(qiymat: T): T {
  return qiymat;
}

qaytarish(42);        // T=number
qaytarish("salom");   // T=string
qaytarish({ id: 1 }); // T={ id: number }

Generic — qayta ishlatish + tur xavfsizligi

any bilan:
  function birinchi(arr: any[]): any
  → tur yo'qoldi, xatolar ko'rinmaydi

Generic bilan:
  function birinchi<T>(arr: T[]): T
  → tur saqlanadi, to'liq tekshiruv

Tez-tez uchraydigan xatolar

Generic o'rniga any ishlatish:

// ❌ — tur yo'qoladi
function ikkitasi(a: any, b: any): any[] { return [a, b]; }

// ✅ — tur saqlanadi
function ikkitasi<T>(a: T, b: T): T[] { return [a, b]; }

ikkitasi(1, 2);         // number[]
ikkitasi("a", "b");     // string[]
ikkitasi(1, "b");       // ❌ — T bir xil bo'lishi kerak

Xulosa

// Generic funksiya
function birinchi<T>(arr: T[]): T { return arr[0]; }

// Ishlatish — T avtomatik aniqlanadi
birinchi([1, 2, 3])     // number
birinchi(["a", "b"])    // string

// T — tur parametri (placeholder)
// Chaqirilganda argument turidan aniqlanadi
// any emas — tur saqlanadi, tekshiruv ishlaydi

Keyingi dars

33-dars: Generic funksiyalar — T parametri, bir nechta parametr