WisarWisar
Dasturlash kitobi/7-QISM — TypeScript19 daqiqa

7.3-bob: Funksiyalar va Generics (chuqur)

7-QISM — TypeScript · 3-mavzu


1. Kirish va motivatsiya

Turlar asosini 7.2-bob bildik. Endi ikki muhim mavzuga o'tamiz: funksiya turlari (parametr, qaytish, overload — chuqur) va TS'ning eng kuchli, eng zarur xususiyati — generics (generiklar — turlarni parametrlash). Generics — boshlovchilar uchun eng "qo'rqinchli" ko'rinadigan, lekin eng kuchli TS xususiyati. Uni o'zlashtirish — TS'da "o'rta"dan "professional"ga o'tish belgisi.

Funksiyalar — har kodning asosi (3-bob: 2.3-JS). TS'da funksiya parametr turlari va qaytish turi bilan ta'riflanadi — bu funksiyani xavfsiz va o'z-o'zini hujjatlaydigan qiladi. Lekin ba'zan funksiya turli turlar bilan ishlashi kerak (masalan, "massivning birinchi elementini qaytar" — number massivi uchun ham, string massivi uchun ham). Bunda any ishlatish — tur xavfsizligini yo'qotadi. Yechim — generics.

Generics — turni parametr sifatida qabul qilish (<T>). Funksiya/class/interface aniq tur bilan emas, o'zgaruvchi tur (T) bilan ishlaydi — ishlatishda aniq tur beriladi. Masalan, birinchi<T>(arr: T[]): T — istalgan turdagi massiv bilan ishlaydi, lekin tur saqlangan (number massiviga number qaytaradi). Bu — Array<T>, Promise<T>, Repository<T> 6.13-bob, useState<T> 11.4-bob — hamma joyda. Generics'siz zamonaviy TS yo'q. Bu bob: funksiya turlari, generics (funksiya/class/interface), constraints — chuqur.

O'xshatish (generics): generic — universal idish/qolip. Oddiy idish (aniq tur) faqat bir narsa uchun (faqat suv idishi). Generic idish (Container<T>) — istalgan narsa uchun (suv, sut, asal — Container<Suv>, Container<Sut>), lekin har biri o'z turini saqlaydi (sut idishidan sut chiqadi, suv emas). Yoki: qolip (<T>) — bir xil shakl, lekin turli material (plastik, metall) bilan to'ldiriladi — har biri o'z xususiyatini saqlaydi.

Nega muhim?

  • Qayta ishlatish + xavfsizlik — generics turli tur bilan, lekin tur saqlangan.
  • Stack'da hamma joyda — Array/Promise/Repository/useState — generics.
  • Professional TS — generics'siz murakkab TS yozib bo'lmaydi.
  • ORM/React — Prisma, TypeORM, React hooks — generics asosida.

2. Nazariya — chuqur tushuntirish

2.1. Funksiya turlari (parametr, qaytish)

ts
// Parametr turlari + qaytish turi (7.2: 2.6)
function summa(a: number, b: number): number {
  return a + b;
}

// Arrow function (2.3-JS)
const kvadrat = (n: number): number => n * n;

// Qaytish turini inference qiladi (yozmasa ham — lekin yozish hujjat)
function ko'paytir(a: number, b: number) {   // qaytish: number (inference)
  return a * b;
}

Funksiya turi: parametr turlari majburiy (inference yo'q parametrlarga — strict — 7.1: 2.8). Qaytish turi — inference qilinadi, lekin yozish tavsiya (hujjat + xato oldini oladi — funksiya kutilgan turni qaytaradimi).

2.2. Ixtiyoriy, default, rest parametrlar

ts
// Ixtiyoriy parametr (? — oxirida)
function salom(ism: string, familiya?: string): string {
  return familiya ? `${ism} ${familiya}` : ism;
}

// Default qiymat
function ko'paytir(a: number, b: number = 2): number {   // b default 2
  return a * b;
}

// Rest parametr (... — qolganlari massiv — 2.8-JS)
function yig'indi(...sonlar: number[]): number {
  return sonlar.reduce((s, n) => s + n, 0);
}
yig'indi(1, 2, 3, 4);   // 10

Parametr turlari: ? (ixtiyoriy — undefined bo'lishi mumkin); = qiymat (default — berilmasa); ...rest (qolganlari massiv — 2.8-JS). Ixtiyoriy oxirida bo'lishi kerak (majburiydan keyin).

2.3. Funksiya turi (type) va callback

ts
// Funksiya turini alohida ta'riflash (7.2: 2.11)
type MatematikAmal = (a: number, b: number) => number;
const summa: MatematikAmal = (a, b) => a + b;   // a, b — inference (number)

// Callback turi (parametr sifatida)
function ishla(data: number[], callback: (n: number) => void): void {
  data.forEach(callback);
}

// Async funksiya — Promise qaytaradi (2.11-JS)
async function userOl(id: number): Promise<User> {   // Promise<User>
  return { id, ism: "Ali" };
}

Funksiya turi ((a: number) => number) — funksiyani parametr/o'zgaruvchi sifatida. Callback (3-bob: 2.3-JS) — tur bilan xavfsiz. AsyncPromise<T> qaytaradi (2.11-JS, 5.1). Bu — har joyda (event handler, callback, async).

2.4. Function overload (bir nom, ko'p signatura)

ts
// Overload — bir funksiya, turli parametr/qaytish (signatura'lar)
function ol(id: number): User;              // signatura 1
function ol(email: string): User;           // signatura 2
function ol(arg: number | string): User {   // amalga oshirish (bitta)
  if (typeof arg === "number") return { id: arg, ism: "Ali" };
  return { id: 1, ism: "Ali" };             // email bo'yicha
}
ol(1);          // User (number signatura)
ol("a@b.uz");   // User (string signatura)

Overload — bir funksiya turli xil chaqirilishi (har xil parametr/qaytish). Signaturalar (e'lon) + bitta amalga oshirish. Kamdan-kam kerak (ko'pincha union/generic afzal), lekin ba'zi API'larda (turli kirish — turli chiqish).

2.5. Generics — muammo va yechim

Muammo: funksiya turli turlar bilan ishlashi kerak, lekin tur saqlanishi kerak:

ts
//  any — tur yo'qoladi (7.1: 2.9)
function birinchiAny(arr: any[]): any {
  return arr[0];
}
const x = birinchiAny([1, 2, 3]);   // x: any (number ekanini bilmaydi!)

//  Generic — tur SAQLANADI
function birinchi<T>(arr: T[]): T {   // T — tur parametri
  return arr[0];
}
const y = birinchi([1, 2, 3]);       // y: number (TS biladi!)
const z = birinchi(["a", "b"]);      // z: string

Generics yechimi: <T>tur parametri (turni keyin aniqlaydi). birinchi<T>(arr: T[]): T — "istalgan T turdagi massiv, T qaytaradi". anydan farqi: tur saqlanadi (number massivi number). Bu — qayta ishlatish + tur xavfsizligi birga.

2.6. Generic sintaksisi va inference

ts
function o'rab<T>(qiymat: T): T[] {     // T — tur parametri (<> ichida)
  return [qiymat];
}

// Inference — TS T ni xulosa qiladi (yozmasa ham)
o'rab(5);          // T = number (avtomatik)
o'rab("salom");    // T = string

// Aniq belgilash (kerak bo'lsa)
o'rab<number>(5);  // T = number (aniq)

Generic inference: ko'pincha T ni yozmasa ham bo'ladi — TS argumentdan xulosa qiladi (o'rab(5) T = number). Aniq belgilash — noaniq holatda (o'rab<string>()). <T> — konvensiya (T = Type; K = Key, V = Value, E = Element).

2.7. Ko'p generic parametr

ts
// Ikki tur parametri
function juftlik<K, V>(kalit: K, qiymat: V): [K, V] {
  return [kalit, qiymat];
}
juftlik("yosh", 25);   // [string, number]

// Obyekt birlashtirish
function birlashtir<T, U>(a: T, b: U): T & U {   // intersection (7.2: 2.12)
  return { ...a, ...b };
}
const r = birlashtir({ ism: "Ali" }, { yosh: 25 });   // { ism: string, yosh: number }

Bir nechta tur parametri (<K, V>, <T, U>) — turli turlarni bog'lash. Map (Map<K, V>), juftlik, birlashtirish. Har parametr mustaqil xulosa qilinadi.

2.8. Generic constraints (extends — cheklov)

Ba'zan generic turga shart kerak (masalan, "T'da length bo'lishi kerak"):

ts
//  T istalgan tur — length bo'lmasligi mumkin
function uzunlik<T>(x: T): number {
  // return x.length;   //  "length T'da yo'q bo'lishi mumkin"
}

//  Constraint — T length'li bo'lishi SHART (extends)
function uzunlik<T extends { length: number }>(x: T): number {
  return x.length;       // OK (T'da length bor — kafolat)
}
uzunlik("salom");        // 5 (string'da length bor)
uzunlik([1, 2, 3]);      // 3 (array'da length bor)
// uzunlik(42);          //  (number'da length yo'q)

Constraint (T extends X) — generic turni cheklaydi (T X'ga mos bo'lishi shart). T extends { length: number } — "T'da length bo'lsin". Bu — generic'ga ishonch beradi (T'ning xususiyatlarini ishlatish mumkin). Eng ko'p ishlatiladigan generic xususiyati.

2.9. keyof va generic (kalit bo'yicha)

ts
// keyof — obyekt kalitlari turi (7.4'da chuqur)
function ol<T, K extends keyof T>(obj: T, kalit: K): T[K] {
  return obj[kalit];     // T[K] — kalitning qiymat turi
}
const user = { ism: "Ali", yosh: 25 };
ol(user, "ism");         // string (T["ism"])
ol(user, "yosh");        // number (T["yosh"])
// ol(user, "boshqa");   //  "boshqa" — user kaliti emas

keyof T — obyekt kalitlari turi ("ism" | "yosh"). K extends keyof T — K obyekt kaliti bo'lishi shart. T[K] — kalitning qiymat turi. Bu — tur-xavfsiz obyekt kirishi (lodash get, ORM select). Kuchli, lekin 7.4'da chuqurroq.

2.10. Generic interface va type

ts
// Generic interface (7.2: 2.5)
interface Quti<T> {
  qiymat: T;
  ol(): T;
}
const sonQuti: Quti<number> = { qiymat: 5, ol() { return this.qiymat; } };

// Generic type (7.2: 2.11)
type Natija<T> = { success: true; data: T } | { success: false; xato: string };

// Generic + default
interface API<T = unknown> {        // default tur (berilmasa unknown)
  data: T;
  status: number;
}

Generic interface/type — qayta ishlatiladigan tipli tuzilma. Quti<T> — istalgan tur uchun quti. Natija<T> — API javob (data turi o'zgaradi). <T = unknown>default tur (berilmasa). Bu — Prisma, React kabi kutubxonalarning asosi.

2.11. Generic class (6.13 bilan)

ts
// Generic class — Repository pattern (6.13: 2.7, 9)
class Repository<T extends { id: number }> {   // constraint: T'da id bor (2.8)
  private items: T[] = [];

  topId(id: number): T | undefined {
    return this.items.find((item) => item.id === id);
  }
  qo'sh(item: T): void {
    this.items.push(item);
  }
}

interface User { id: number; ism: string; }
const userRepo = new Repository<User>();   // T = User
userRepo.qo'sh({ id: 1, ism: "Ali" });
const u = userRepo.topId(1);               // User | undefined (tipli!)

Generic class — turli turlar uchun bir class (Repository, Repository). T extends { id: number } — constraint (T'da id kerak). Bu — TypeORM Repository 6.13-bob, umumiy CRUD class. Qayta ishlatish + tur xavfsizligi.

2.12. Built-in generics (Array, Promise, ...)

JS/TS'ning ko'p tuzilmasi — generic (allaqachon ishlatgansiz):

ts
Array<number>           // number[] (massiv)
Promise<User>           // async natija (2.11-JS)
Map<string, number>     // kalit-qiymat (2.9-JS)
Set<string>             // to'plam (2.9-JS)
Record<string, User>    // obyekt (utility — 7.4)

Siz generics'ni allaqachon ishlatgansiz: Promise<User> 5.1-bob, Array<T>, Map<K,V> (2.9-JS). Bular — built-in generics. Tushunganingizdan keyin — o'zingiz yozasiz. React useState<T> 11.4-bob ham generic.

2.13. Generic utility funksiyalar

ts
// Tur-xavfsiz utility'lar (qayta ishlatiladigan)
function oxirgi<T>(arr: T[]): T | undefined {
  return arr[arr.length - 1];
}

function guruhla<T, K extends string | number>(
  arr: T[], kalitFn: (item: T) => K
): Record<K, T[]> {                       // Record (7.4)
  return arr.reduce((acc, item) => {
    const kalit = kalitFn(item);
    (acc[kalit] ??= []).push(item);
    return acc;
  }, {} as Record<K, T[]>);
}
// guruhla(users, u => u.rol)  { admin: [...], user: [...] } (tipli)

Generic utility'lar — turli tur bilan ishlaydigan, tur-xavfsiz yordamchilar (lodash kabi). oxirgi<T>, guruhla<T, K> — qayta ishlatiladigan. Bu — real loyihada generics'ning amaliy foydasi.

2.14. Generic best practices

text
   any o'rniga generic (tur saqlanadi — 2.5)
   Inference'dan foydalaning (T ni yozmang — 2.6)
   Constraint (extends) kerak bo'lganda (T'ni cheklash — 2.8)
   Ma'noli nom (T, K, V — yoki to'liq: TData, TKey)
   Ortiqcha generic'dan qoching (kerak bo'lsa — qachon turlar bog'liq)
   Default tur (<T = unknown>) — qulaylik 2.10-bob
   Built-in generics'ni bil (Array/Promise/Map — 2.12)

Generic'ni ortiqcha ishlatmang: generic — turlar bog'liq bo'lganda (kirish turi chiqish turini belgilaydi). Agar tur bog'liq bo'lmasa — generic keraksiz (oddiy tur yetadi). "Har joyga " — yomon (murakkablik).

2.15. Generics qachon kerak (xulosa)

text
  Generic KERAK:
   Funksiya/class turli tur bilan ishlaydi, lekin tur SAQLANISHI kerak
   Kirish turi chiqish turini belgilaydi (birinchi<T>(arr): T)
   Konteyner/wrapper (Quti<T>, Repository<T>, Promise<T>)
   Qayta ishlatiladigan utility (turli tur)

  Generic KERAK EMAS:
   Tur aniq va o'zgarmas (oddiy tur yetadi)
   Turlar bog'liq emas (any'ni yashirish uchun emas)

3. Sintaksis — tez ma'lumotnoma

ts
// Funksiya (2.1-2.3)
function f(a: number, b?: string, c = 10): number { return a; }
type Fn = (x: number) => string;
async function g(): Promise<User> { ... }

// Generics (2.5-2.11)
function birinchi<T>(arr: T[]): T { return arr[0]; }        // funksiya
interface Quti<T> { qiymat: T; }                            // interface
class Repo<T extends { id: number }> { ... }                // class + constraint
function ol<T, K extends keyof T>(o: T, k: K): T[K] { ... } // keyof (2.9)

4. Batafsil kod namunalari

Misol 1 — Funksiya turlari (2.1-2.3)

ts
// Parametr + qaytish (2.1)
function chegirma(narx: number, foiz: number): number {
  return narx * (1 - foiz / 100);
}

// Ixtiyoriy, default, rest (2.2)
function xabar(matn: string, prefiks = "[INFO]", ...qoshimcha: string[]): string {
  return `${prefiks} ${matn} ${qoshimcha.join(" ")}`;
}

// Funksiya turi + callback (2.3)
type Filter<T> = (item: T) => boolean;       // generic funksiya turi
function filtrla<T>(arr: T[], fn: Filter<T>): T[] {
  return arr.filter(fn);
}
filtrla([1, 2, 3, 4], (n) => n > 2);         // [3, 4] (n: number — inference)

Misol 2 — Generic asoslari (2.5, 2.6)

ts
// Identity (oddiy generic)
function bir xil<T>(qiymat: T): T {
  return qiymat;
}

// Massiv utility'lari (tur saqlangan — 2.5)
function birinchi<T>(arr: T[]): T | undefined { return arr[0]; }
function oxirgi<T>(arr: T[]): T | undefined { return arr.at(-1); }
function teskari<T>(arr: T[]): T[] { return [...arr].reverse(); }

const sonlar = birinchi([1, 2, 3]);    // number | undefined
const ismlar = teskari(["a", "b"]);    // string[]

Misol 3 — Constraints (extends — 2.8)

ts
// T'da id bo'lishi shart (constraint — 2.8)
function topId<T extends { id: number }>(arr: T[], id: number): T | undefined {
  return arr.find((item) => item.id === id);
}

interface User { id: number; ism: string; }
interface Product { id: number; nom: string; }

topId<User>([{ id: 1, ism: "Ali" }], 1);        // User | undefined
topId<Product>([{ id: 1, nom: "Telefon" }], 1);  // Product | undefined
// topId([{ nom: "x" }], 1);   //  id yo'q (constraint buzildi)

Misol 4 — keyof generic (tur-xavfsiz kirish — 2.9)

ts
// Obyekt maydonini tur-xavfsiz olish (2.9)
function ol<T, K extends keyof T>(obj: T, kalit: K): T[K] {
  return obj[kalit];
}

const user = { ism: "Ali", yosh: 25, faol: true };
const ism = ol(user, "ism");      // string (T["ism"])
const yosh = ol(user, "yosh");    // number
const faol = ol(user, "faol");    // boolean
// ol(user, "email");             //  "email" — user kaliti emas

// Bir necha maydonni olish (pluck)
function pluck<T, K extends keyof T>(arr: T[], kalit: K): T[K][] {
  return arr.map((item) => item[kalit]);
}
pluck([user], "ism");             // string[]

Misol 5 — Generic interface va type (2.10)

ts
// API javob turi (generic — 2.10)
type ApiResponse<T> =
  | { success: true; data: T }
  | { success: false; error: string };

async function userOl(id: number): Promise<ApiResponse<User>> {
  try {
    const user = await fetchUser(id);
    return { success: true, data: user };       // data: User
  } catch (err) {
    return { success: false, error: "Topilmadi" };
  }
}

const javob = await userOl(1);
if (javob.success) console.log(javob.data.ism);  // narrowing 7.5-bob — data: User
else console.log(javob.error);

Misol 6 — Generic class (Repository — 2.11)

ts
// Umumiy CRUD repository (generic class — 2.11, 6.13)
class InMemoryRepository<T extends { id: number }> {
  private items = new Map<number, T>();          // Map<number, T> (2.12)

  hammasi(): T[] { return [...this.items.values()]; }
  topId(id: number): T | undefined { return this.items.get(id); }
  saqla(item: T): T { this.items.set(item.id, item); return item; }
  ochir(id: number): boolean { return this.items.delete(id); }
}

interface User { id: number; ism: string; }
interface Product { id: number; nom: string; narx: number; }

const userRepo = new InMemoryRepository<User>();      // T = User
const productRepo = new InMemoryRepository<Product>(); // T = Product
userRepo.saqla({ id: 1, ism: "Ali" });                 // tipli
const u = userRepo.topId(1);                           // User | undefined

Misol 7 — Generic utility funksiyalar (2.13)

ts
// guruhla — array'ni kalit bo'yicha guruhlash (2.13)
function guruhla<T, K extends string | number | symbol>(
  arr: T[], kalitFn: (item: T) => K
): Record<K, T[]> {
  return arr.reduce((acc, item) => {
    const kalit = kalitFn(item);
    (acc[kalit] ??= []).push(item);
    return acc;
  }, {} as Record<K, T[]>);
}

const users = [
  { ism: "Ali", rol: "admin" },
  { ism: "Vali", rol: "user" },
  { ism: "Hasan", rol: "admin" },
];
const rolBoyicha = guruhla(users, (u) => u.rol);
// { admin: [Ali, Hasan], user: [Vali] } — tipli!

// noyob — takrorlanmas
function noyob<T>(arr: T[]): T[] {
  return [...new Set(arr)];          // Set<T> (2.12)
}
noyob([1, 1, 2, 3, 3]);              // [1, 2, 3]

Misol 8 — Async generic (Promise — 2.3, 2.12)

ts
// Generic async wrapper (xato boshqaruvi — 5.10 ruhida)
async function xavfsizSorov<T>(
  fn: () => Promise<T>
): Promise<{ data: T; xato: null } | { data: null; xato: Error }> {
  try {
    const data = await fn();
    return { data, xato: null };       // muvaffaqiyat
  } catch (err) {
    return { data: null, xato: err as Error };   // xato
  }
}

// Ishlatish (tur saqlangan)
const natija = await xavfsizSorov(() => fetchUser(1));   // data: User | null
if (natija.data) console.log(natija.data.ism);           // narrowing (7.5)

5. To'g'ri va noto'g'ri holatlar

1) any o'rniga generic

ts
//  any — tur yo'qoladi (2.5)
function birinchi(arr: any[]): any { return arr[0]; }

//  generic — tur saqlanadi
function birinchi<T>(arr: T[]): T { return arr[0]; }

2) Generic'ni ortiqcha ishlatish

ts
//  keraksiz generic (turlar bog'liq emas — 2.14)
function salom<T>(ism: string): string { return ism; }

//  oddiy tur (T kerak emas)
function salom(ism: string): string { return ism; }

3) Constraint'siz xususiyatga murojaat

ts
//  T'da length bo'lmasligi mumkin (2.8)
function uzunlik<T>(x: T) { return x.length; }   // xato

//  constraint
function uzunlik<T extends { length: number }>(x: T) { return x.length; }

4) Qaytish turini yozmaslik (muhim funksiya)

ts
//  noaniq qaytish (xato o'tib ketadi)
function hisobla(a: number) { return a > 0 ? a : "manfiy"; }   // number | string (kutilmagan?)

//  aniq qaytish turi (xato ushlanadi)
function hisobla(a: number): number { return a > 0 ? a : -a; }

5) Ko'p inference o'rniga aniq belgilash (noaniq)

ts
// Bo'sh massiv — inference bilmaydi
const arr = [];   // any[] (yomon)
const arr2: number[] = [];   //  aniq

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Property 'x' does not exist on type 'T'

Sababi: generic T'da xususiyat bo'lmasligi mumkin (constraint yo'q — 2.8). Yechimi: T extends { x: ... } (constraint).

Xato 2 — Argument of type 'X' is not assignable to parameter

Sababi: tur mos emas, yoki constraint buzildi 2.8-bob. Yechimi: to'g'ri tur; constraint'ga mos argument.

Xato 3 — Generic tur unknown/noaniq

Sababi: inference ishlamadi (bo'sh massiv, noaniq). Yechimi: aniq belgilash (birinchi<number>(...)).

Xato 4 — 'T' is declared but never used

Sababi: generic e'lon qilindi, lekin ishlatilmadi (keraksiz — 2.14). Yechimi: generic'ni olib tashlang (oddiy tur).

Xato 5 — Funksiya kutilmagan tur qaytaradi

Sababi: qaytish turi yozilmagan (inference noto'g'ri — 2.1). Yechimi: aniq qaytish turi (xato ushlanadi).

Xato 6 — keyof xatosi

Sababi: K extends keyof T constraint yo'q 2.9-bob. Yechimi: constraint qo'sh; kalit obyektga mos.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Funksiyalar (2.3-JS): TS funksiya turlari.
  • Turlar 7.2-bob: generic — turlar ustida.
  • Ilg'or turlar 7.4-bob: keyof, mapped — generic bilan.
  • Promise/async (2.11-JS, 5.1): Promise.
  • Map/Set (2.9-JS): Map<K,V>, Set.
  • TypeORM 6.13-bob: Repository.
  • React 11.4-bob: useState, hooks.
  • Zod 5.9-bob: infer.
  • Utility funksiyalar: lodash kabi generic.
  • SOLID (9): generic interface (DIP).

8. Eng yaxshi amaliyotlar (best practices)

  • any o'rniga generic (tur saqlanadi — 2.5).
  • Inference'dan foydalaning (T ni yozmang, kerak bo'lsa belgilang — 2.6).
  • Constraint (extends) kerak bo'lganda (T'ni cheklash — 2.8).
  • Qaytish turini yozing (muhim funksiya — hujjat + xato — 2.1).
  • Ortiqcha generic'dan qoching (turlar bog'liq bo'lganda — 2.14).
  • Ma'noli generic nom (T, K, V yoki TData — 2.14).
  • Default tur (<T = unknown> — qulaylik — 2.10).
  • Built-in generics'ni biling (Array/Promise/Map/Record — 2.12).
  • keyof bilan tur-xavfsiz kirish (obyekt maydoni — 2.9).
  • Generic class — qayta ishlatiladigan (Repository — 2.11).

9. Amaliy loyiha: "Generic Utility Kutubxonasi"

Funksiya turlari va generics'ni mustahkamlash.

Maqsad

Tur-xavfsiz, qayta ishlatiladigan generic utility'lar va generic repository class yaratish.

Talablar (requirements)

  1. Funksiya turlari: parametr/qaytish/ixtiyoriy/default/rest (Misol 1, 2.1, 2.2).
  2. Array utility'lar (generic): birinchi, oxirgi, teskari, noyob (Misol 2, 7, 2.5).
  3. Constraint: topId (T extends {id}), uzunlik (Misol 3, 2.8).
  4. keyof: ol/pluck (tur-xavfsiz maydon — Misol 4, 2.9).
  5. Generic interface/type: ApiResponse (Misol 5, 2.10).
  6. Generic class: InMemoryRepository (CRUD — Misol 6, 2.11).
  7. guruhla: kalit bo'yicha guruhlash (Misol 7, 2.13).
  8. Async generic: xavfsizSorov (Misol 8, 2.3).
  9. Built-in generics: Map/Set/Promise ishlatilgan 2.12-bob.
  10. strict: any'siz, tur saqlangan 7.1-bob.

Maslahatlar (hint)

  • any o'rniga <T> (2.5, 1-xato).
  • Constraint: T extends {...} (2.8, 1-xato).
  • keyof: K extends keyof T, T[K] 2.9-bob.
  • Inference (T ni yozma — 2.6).
  • Ortiqcha generic'dan qoch (2.14, 2-xato).
  • Record<K, T[]> (guruhlash — 7.4).

"Tayyor" mezonlari (acceptance criteria)

  • Funksiya turlari (ixtiyoriy/default/rest).
  • Generic array utility'lar (tur saqlangan).
  • Constraint (extends).
  • keyof (tur-xavfsiz kirish).
  • Generic interface/type (ApiResponse).
  • Generic class (repository).
  • guruhla (Record).
  • Async generic.
  • Built-in generics.
  • any'siz, strict.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda funksiya turlari va generics'ni chuqur o'rgandik:

  • Funksiya turlari (parametr/qaytish — 2.1; ixtiyoriy/default/rest — 2.2; funksiya turi/callback — 2.3; overload — 2.4).
  • Generics (<T> — tur parametri — muammo/yechim — 2.5); inference 2.6-bob; ko'p parametr 2.7-bob; constraints (T extends X — 2.8); keyof 2.9-bob.
  • Generic interface/type/class (2.10, 2.11); built-in (Array/Promise/Map — 2.12); generic utility'lar 2.13-bob.
  • Qachon generic (turlar bog'liq — saqlanishi kerak — 2.15); ortiqcha qochish 2.14-bob.

Keyingi bob — 7.4-bob: Ilg'or turlar — union, intersection, conditional, mapped, utility types. Generics'ni bildik; endi TS'ning eng kuchli, "sehrli" qismiga — ilg'or turlarga — o'tamiz: conditional types (shartli tur), mapped types (tur o'zgartirish), va utility types (Partial, Pick, Omit, Record — tayyor kuchli vositalar). Bu — TS'ni "ekspert" darajaga olib chiqadi.


Foydalanilgan rasmiy/ishonchli manbalar

  • typescriptlang.org — Functions, Generics, Generic Constraints, keyof
  • TypeScript Handbook — More on Functions, Generics; built-in generic types
  • TS docs — generic classes, generic interfaces, constraints

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
7.3-bob: Funksiyalar va Generics (chuqur) — Wisar