IlmHamroh
JavaScript Full-stack/15-qism. TypeScript20/47-dars18 daqiqa
Mundarija (33)

TypeScript generics: turni parametr qilish — <T>, identity va first<T>

Qisqacha: Generic funksiya turni ham parametr sifatida oladi: function first<T>(items: T[]): T | undefined. T — "chaqirilganda aniqlanadigan tur". first([35000, 28000]) da TypeScript T = number ekanini o'zi chiqaradi va natija number | undefined bo'ladi. any dan farqi — tur ma'lumoti yo'qolmaydi.

Bu darsda

  • <T> tur parametri bilan generic funksiya yozasiz.
  • Tur argumentini TypeScript qanday chiqarishini (inference) va qachon uni o'zingiz yozishni bilasiz.
  • Generic, any va unknown farqini misolda ko'rsata olasiz.
  • Array<T>, Map<K, V>, Promise<T> kabi tayyor generic turlarni o'qiysiz.
  • "Yolg'onchi generic" tuzog'ini taniysiz — T faqat natijada bo'lsa.

Oldin bilishingiz kerak: enum va uning muqobillari, Funksiyalarni tiplash, any, unknown, never, Massiv va tuple turlari.

1. Nega bu kerak?

O'tgan darsda as const va union bilan aniq qiymatlar to'plamini yozdik. Endi teskari muammo: funksiya har xil turlar bilan ishlashi kerak, lekin har birining turini saqlab qolishi kerak.

Sardor ro'yxatning birinchi elementini oladigan funksiya yozmoqchi. Narxlar uchun ham, mehmonlar uchun ham, buyurtmalar uchun ham kerak. Birinchi urinish — har tur uchun alohida:

ts
function firstPrice(items: readonly number[]): number | undefined {
  return items[0];
}
function firstGuest(items: readonly string[]): string | undefined {
  return items[0];
}
console.log(firstPrice([35000])); // 35000
console.log(firstGuest(["Malika"])); // Malika

Ikki funksiyaning tanasi bir xil, faqat turlar farq qiladi. Ertaga buyurtmalar, stollar, bronlar uchun yana uchtasi kerak bo'ladi.

Ikkinchi urinish — any bilan bitta funksiya:

ts
function first(items: readonly any[]): any {
  return items[0];
}
const price = first([35000, 28000]);
console.log(price.toUpperCase());

tsc — xatosiz. Node esa:

text
TypeError: price.toUpperCase is not a function

any funksiyani "universal" qildi, lekin tur ma'lumotini butunlay o'chirdi: price — any, unga istalgan metodni chaqirsa bo'ladi. any, unknown, never darsidagi xavf. Bizga ikkalasi kerak: bitta funksiya va har chaqiruvda aniq tur.

2. Tur parametri <T>

2.1 Birinchi generic funksiya

ts
function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}

const price = first([35000, 28000]);
const guest = first(["Malika", "Bobur"]);
console.log(price, guest); // 35000 Malika

Qatorni bo'lib o'qiymiz:

  • first<T> — funksiya nomidan keyin burchak qavsda tur parametri (type parameter) e'lon qilindi. T — "hozircha noma'lum tur, chaqirilganda aniqlanadi".
  • items: readonly T[] — "T turidagi elementlar ro'yxati".
  • : T | undefined — "o'sha T turidagi element yoki undefined" (bo'sh ro'yxat uchun).

Hover'da: const price: number | undefined, const guest: string | undefined. Bitta funksiya, lekin har chaqiruvda o'z turi.

Kundalik o'xshatish: oddiy parametr — qiymat uchun bo'sh joy (items), tur parametri — tur uchun bo'sh joy (T). Xuddi blanka: "F.I.Sh: ____" kabi, T — "tur: ____". Chaqirilganda u to'ldiriladi. Bunday funksiya generic (umumlashtirilgan) deyiladi. T — an'anaviy nom (type), lekin istalgan nom bo'lishi mumkin: Item, TValue.

2.2 T ni kim to'ldiradi?

Ikki yo'l bor. Birinchisi — TypeScript argumentlardan o'zi chiqaradi (tur argumentini chiqarish, type argument inference). first([35000, 28000]) da items number[] — demak T = number. Bu Tur chiqarish darsidagi inference'ning davomi.

flowchart LR
  A["first([35000, 28000])"] --> B["readonly T[]<br/>⇐ number[]"]
  B --> C["T = number"]
  C --> D["natija:<br/>number | undefined"]

Ikkinchi yo'l — tur argumentini o'zingiz burchak qavsda yozasiz:

ts
function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}

const id = first<number>([101, 102]);
console.log(id); // 101

first<number>(…) — "T — bu number". Odatda shart emas: TypeScript to'g'ri chiqaradi. Lekin shunda TypeScript argumentlarni ham shu turga qarab tekshiradi:

ts
function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}
const name = first<string>([1, 2]);

Kompilyator:

text
TS2322: Type 'number' is not assignable to type 'string'.
TS2322: Type 'number' is not assignable to type 'string'.

Tarjimasi: "number turini string turiga berib bo'lmaydi". T = string deb aytdik — demak items string[] bo'lishi kerak. Ikki sonning har biri uchun bittadan xato.

2.3 Eng sodda generic: identity

Generic'larni tushuntirishda klassik misol — qiymatni o'zgarishsiz qaytaradigan funksiya:

ts
function identity<T>(value: T): T {
  return value;
}

const a = identity("osh");
let b = identity("osh");
const c = identity(35000);
console.log(a, b, c); // osh osh 35000

Hover'dagi turlar qiziq:

Kod Tur
const a = identity("osh") "osh"
let b = identity("osh") string
const c = identity(35000) 35000

Tur chiqarish darsidagi qoida generic'da ham ishlaydi: const — literal tur, let — kengaygan tur. T chaqiruvdan chiqariladi, natija esa qayerga yozilishiga qarab kengayadi yoki aniq qoladi.

identity amalda kam ishlatiladi, lekin u g'oyani eng toza ko'rsatadi: kirgan tur — chiqqan tur. Funksiya qiymatni "ushlab", turini yo'qotmasdan qaytardi.

T natijaning ichida ham kelishi mumkin. Masalan, qiymatni obyektga o'raydigan funksiya:

ts
function wrap<T>(value: T): { value: T } {
  return { value };
}

const box = wrap(35000);
const list = wrap(["Osh", "Manti"]);
console.log(box.value + 5000, list.value.length); // 40000 2

Hover'da box: { value: number }, list: { value: string[] }. T qayerda turmasin — massivda, obyekt maydonida, tuple'da — chaqiruvda bir xil turga almashtiriladi.

2.4 T chiqarilmasa — unknown

Inference'ga argument kerak. T hech bir parametrda bo'lmasa, TypeScript uni chiqara olmaydi va unknown deb oladi:

ts
function emptyList<T>(): T[] {
  return [];
}

const guests = emptyList();
const names = emptyList<string>();
names.push("Malika");
console.log(guests.length, names); // 0 [ 'Malika' ]

Hover'da guests: unknown[] — undan foyda kam, har elementni tekshirish kerak. names: string[] — tur argumenti yozilgan. Qoida: T argumentlardan chiqarilmaydigan generic'ni chaqirganda tur argumentini yozing. Bu xuddi bo'sh massivga tur yozish qoidasining o'zi.

Tekshirib ko'ring: first(["Osh", 35000]) natijasining turi qanday?

Javob

string | number | undefined. Massiv (string | number)[] deb chiqarildi (Massiv va tuple turlari), demak T = string | number. Natijaga bo'sh ro'yxat uchun undefined qo'shildi.

3. Generic, any va unknown

3.1 Uchala variant yonma-yon

unknown ham "istalgan tur" degani. Nega u yetmaydi?

ts
function firstUnknown(items: readonly unknown[]): unknown {
  return items[0];
}
const price = firstUnknown([35000]);
price.toFixed(0);

Kompilyator:

text
TS18046: 'price' is of type 'unknown'.

Tarjimasi: "price ning turi — unknown". TypeScript aytyapti: "men bu qiymat nima ekanini bilmayman, avval tekshiring". unknown xavfsiz, lekin noqulay: funksiya price son ekanini "unutdi", endi har safar uni qaytadan tekshirish kerak (typeof price === "number"). Biz esa buni bilamiz — ro'yxatga son berdik.

Variant Ichkarida Natija turi Xavfsizmi
any[] → any hamma narsa mumkin any — tekshiruv o'chadi yo'q
unknown[] → unknown hech narsa mumkin emas unknown — har safar toraytirish ha, lekin noqulay
T[] → T T haqida hech narsa ma'lum emas chaqiruvdagi aniq tur ha va qulay

Generic — "kirgan va chiqqan turlar o'rtasidagi bog'lanish". any ham, unknown ham bu bog'lanishni uzadi. Generic esa uni saqlaydi: "nima bersang, o'shaning elementini qaytaraman".

3.2 Funksiya ichida T — "qora quti"

Generic funksiya ichida T haqida hech narsa ma'lum emas. U son ham, satr ham, obyekt ham bo'lishi mumkin. Shuning uchun uning xususiyatlariga murojaat qilib bo'lmaydi:

ts
function lengthOf<T>(value: T): number {
  return value.length;
}

Kompilyator:

text
TS2339: Property 'length' does not exist on type 'T'.

Tarjimasi: "T turida length xususiyati yo'q". Mantiqan to'g'ri: lengthOf(35000) deb chaqirilsa, sonda length yo'q. "T da kamida length bo'lsin" degan talabni qanday qo'yish — Generic cheklovlar va keyof darsining mavzusi (T extends …). Hozircha qoida: cheklovsiz T bilan faqat uni saqlash, uzatish va qaytarish mumkin.

4. Generic va callback

4.1 T parametrlar orasida bog'lanadi

Generic'ning kuchi — bir nechta parametrni bitta tur bilan bog'lash. Ro'yxatni shart bo'yicha filtrlaydigan funksiya:

ts
function keepIf<T>(
  items: readonly T[],
  test: (item: T) => boolean,
): T[] {
  const result: T[] = [];
  for (const item of items) {
    if (test(item)) result.push(item);
  }
  return result;
}

const prices = [35000, 28000, 30000, 5000];
const cheap = keepIf(prices, (p) => p < 30000);
console.log(cheap); // [ 28000, 5000 ]

prices dan T = number chiqarildi. Endi callback'dagi p ham avtomatik number — biz unga tur yozmadik. Kompilyator chaqiruvni shunday "yechadi":

Qadam Nima bo'ldi? Natija
1 items ga prices keldi: number[] readonly T[] ⇐ number[]
2 Moslashtirib, T topildi T = number
3 test ning turiga T qo'yildi (item: number) => boolean
4 Callback'dagi p shu turdan oldi p: number
5 Natija turiga ham T qo'yildi cheap: number[]

Bitta T uch joyni bog'ladi: kirish ro'yxati, callback parametri va natija. Funksiyalarni tiplash darsidagi kontekstdan chiqarish (contextual typing) generic orqali ishladi.

Callback ichida xato qilsak:

ts
function keepIf<T>(
  items: readonly T[],
  test: (item: T) => boolean,
): T[] {
  return items.filter(test);
}
const dishes = ["Osh", "Manti", "Lag'mon"];
const short = keepIf(dishes, (d) => d.toFixed(0) === "0");

Kompilyator:

text
TS2551: Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?

Tarjimasi: "string turida toFixed xususiyati yo'q. fixed ni nazarda tutdingizmi?" d — string, chunki T = string. toFixed — son metodi. (fixed — satrlarning juda eski, HTML yasaydigan metodi, TypeScript shunchaki yaqin nomni taklif qildi.)

4.2 Bir chaqiruvda T bitta

Bitta chaqiruvda T faqat bitta turga teng bo'ladi:

ts
function pair<T>(a: T, b: T): T[] {
  return [a, b];
}
pair(35000, "Osh");

Kompilyator:

text
TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

Tarjimasi: "string turidagi argumentni number turidagi parametrga berib bo'lmaydi". TypeScript birinchi argumentdan T = number ni chiqardi, ikkinchisi esa mos kelmadi. Aralash juftlik ataylab kerak bo'lsa — tur argumentini yozing: pair<string | number>(35000, "Osh"). Ikki xil turni alohida kuzatish uchun ikkita tur parametri kerak — buni keyingi darsda ko'ramiz.

Tekshirib ko'ring: keepIf(["Malika", "Bobur"], (name) => name.length > 5) — name ning turi va natija qanday?

Javob

name — string (T = string). Natija — [ 'Malika' ], turi string[]. "Malika" — 6 harf, "Bobur" — 5, 5 > 5 esa false.

5. Tayyor generic turlar

5.1 Siz ularni allaqachon ishlatgansiz

Burchak qavsli turlarni avval ham ko'rgansiz — endi ular nima ekanini bilasiz:

Tur Ma'nosi Qayerda ko'rgansiz
Array<T> T lar massivi (T[] bilan bir xil) Massiv va tuple turlari
Map<K, V> K kalitli, V qiymatli lug'at Index signature va Record
Set<T> takrorlanmas T lar JSDoc
Promise<T> kelajakda T qiymat beradigan va'da async funksiyalar
Record<K, V> K kalitlarga V qiymatlar Index signature va Record

Map<K, V> — ikki tur parametrli generic. Promise<T> — async funksiya natijasi: async function load(): Promise<string> — "oxir-oqibat satr beradi" (Async kod va xatolarni tiplash darsida batafsil).

5.2 Massiv metodlari ham generic

map — eng ko'p ishlatiladigan generic metod. Uning turi soddalashtirib aytilganda: map<U>(fn: (item: T) => U): U[] — "har elementni U ga aylantir, U lar massivini qaytar":

ts
const prices = [35000, 28000];
const labels = prices.map((p) => `${p} so'm`);
console.log(labels); // [ "35000 so'm", "28000 so'm" ]

T = number (massivdan), U = string (callback natijasidan) — hover'da const labels: string[]. Siz hech qanday tur yozmadingiz, lekin TypeScript ikkita tur parametrini chiqardi.

5.3 Bo'sh konteynerga tur argumenti

Inference'ga qiymat kerak. Bo'sh Map yoki Set yaratilganda qiymat yo'q — tur argumentini yozing:

ts
const stock = new Map<string, number>();
stock.set("osh", 12);
console.log(stock.get("osh")); // 12

new Map() siz yozilsa, tur Map<any, any> bo'lardi va stock.get(…) ham any qaytarardi — strict bu holatda xato bermaydi. Bu Index signature va Record darsidagi countDishes da ham shunday edi.

Tekshirib ko'ring: const tags = new Set(["achchiq", "vegetarian"]); — tur argumenti yozish kerakmi? tags ning turi qanday?

Javob

Kerak emas. Konstruktorga qiymatlar berildi, TypeScript ulardan T = string ni chiqardi: Set<string>. Tur argumenti faqat bo'sh konteynerda (new Set()) yoki chiqarilgan tur sizga mos kelmaganda kerak.

6. Generic arrow funksiya

Arrow funksiyada tur parametri qavslardan oldin yoziladi:

ts
const last = <T,>(items: readonly T[]): T | undefined => items.at(-1);

console.log(last(["Osh", "Manti"])); // Manti

<T,> dagi vergul — .ts faylda shart emas (<T> ham ishlaydi). Lekin React fayllarida (.tsx, 17-qismdan) <T> HTML teg bilan adashtiriladi, vergul esa "bu tur parametri" deb aniqlashtiradi. Ko'p jamoalar shu sababli doim <T,> yozadi.

7. TypeScript ushlamaydigan tuzoq: yolg'onchi generic

Generic'lar ham faqat turlar — ishlash paytida ular yo'q. T hech narsani tekshirmaydi. Mana xavfli naqsh:

ts
function parse<T>(json: string): T {
  return JSON.parse(json);
}

const dish = parse<{ price: number }>('{"narx": 35000}');
console.log(dish.price.toFixed(0));

tsc — xatosiz. Node esa:

text
TypeError: Cannot read properties of undefined (reading 'toFixed')

Serverdan narx keldi, price emas. parse<{ price: number }> — bu tekshiruv emas, type assertion (as) ning niqoblangan shakli: JSON.parse any qaytaradi, T esa unga istalgan turni "yopishtiradi".

Belgisi: T faqat natijada uchraydi, parametrlarda yo'q. Haqiqiy generic'da T kirish va chiqishni bog'laydi (first(items: T[]): T). Bu yerda esa bog'laydigan narsa yo'q — T ni chaqiruvchi o'zi "e'lon qiladi". To'g'ri yo'l — unknown qaytarish va ishlash paytida tekshirish (API ma'lumotlarini tiplash darsida). Keraksiz va xavfli generic'larni Generics ilg'or amaliyoti darsida batafsil ko'ramiz.

8. Generic qachon kerak emas?

Generic — kuchli vosita, lekin har joyda emas. Ikki oddiy savol:

  1. Funksiya bitta aniq tur bilan ishlaydimi? totalPrice(prices: number[]) faqat sonlarni qo'shadi — unga T kerak emas. totalPrice<T> yozsangiz, ichkarida + ishlatib bo'lmaydi (T — qora quti) va kod faqat murakkablashadi.
  2. T kamida ikki joyni bog'laydimi? first(items: T[]): T — parametr va natijani bog'laydi, foydali. log<T>(value: T): void — T bitta joyda, natijada yo'q. Bu log(value: unknown): void bilan bir xil, faqat chalkashroq.

Qoida qisqa: generic — turlar orasidagi bog'lanish uchun. Bog'lanish bo'lmasa, oddiy tur yoki unknown yetadi. Bu mavzuni Generics ilg'or amaliyoti darsida chuqurroq ko'ramiz.

9. Ko'p uchraydigan xatolar

9.1 Generic o'rniga any

function first(items: any[]): any — natija any, xatolar jim o'tadi. Tuzatish: first<T>(items: readonly T[]): T | undefined.

9.2 Cheklovsiz T ning xususiyatiga murojaat

TS2339: Property 'length' does not exist on type 'T'. Tuzatish: keyingi darsdagi cheklov — T extends { length: number }.

9.3 Bo'sh konteyner tur argumentisiz

new Map() — Map<any, any>. Tuzatish: new Map<string, number>().

9.4 T faqat natijada

parse<T>(json): T — tekshiruvsiz va'da. Tuzatish: unknown qaytaring va toraytiring.

9.5 Natijada undefined ni unutish

first<T>(items: T[]): T deb yozish — bo'sh ro'yxatda tur yolg'on gapiradi. Tuzatish: T | undefined.

10. Mashqlar

1-mashq (oson): Turlarni ayting

ts
function identity<T>(value: T): T {
  return value;
}
function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}
const x = identity(true);
const y = first([5000, 28000]);
const z = ["a", "b"].map((s) => s.length);
console.log(x, y, z); // true 5000 [ 1, 1 ]

x ning turi: [:true]. y ning turi number | …: [:undefined]. z ning turi: ].

Yechim
  • x — true: const va literal argument, T = true.
  • y — number | undefined: T = number, bo'sh ro'yxat uchun undefined.
  • z — number[]: map da U callback natijasidan chiqarildi (s.length — son).

2-mashq (o'rta): findBy ni yozing

Ro'yxatdan shartga mos birinchi elementni topadigan generic funksiya yozing: findBy(items, test). Natija — element yoki undefined. Array.prototype.find ishlatmang — sikl bilan yozing.

ts
const menu = [
  { name: "Osh", price: 35000 },
  { name: "Manti", price: 30000 },
];
const found = findBy(menu, (d) => d.price < 32000);
console.log(found?.name); // Manti
Yechim
ts
function findBy<T>(
  items: readonly T[],
  test: (item: T) => boolean,
): T | undefined {
  for (const item of items) {
    if (test(item)) return item;
  }
  return undefined;
}

const menu = [
  { name: "Osh", price: 35000 },
  { name: "Manti", price: 30000 },
];
const found = findBy(menu, (d) => d.price < 32000);
console.log(found?.name); // Manti
console.log(findBy(menu, (d) => d.price > 50000)); // undefined
  • T = { name: string; price: number } — menu dan chiqarildi, d ham shu tur.
  • found?.name — found undefined bo'lishi mumkin, ?. buni hisobga oladi.
  • Natija turi T | undefined — any bo'lganda found.name jim o'tib, topilmaganda yiqilardi.

3-mashq (qiyin): Amaliy tajriba — ro'yxat yordamchilari

Mashq kurs/mashqlar/15/ papkasida. 20-generics/list.ts faylida to'rtta generic funksiya yozing:

  • first(items) va last(items) — element yoki undefined. Ishora: items.at(-1) — oxirgi element (Massiv: yaratish va elementga murojaat).
  • chunk(items, size) — ro'yxatni size tadan bo'laklarga bo'lsin: [1, 2, 3, 4, 5], 2 → [[1, 2], [3, 4], [5]]. size musbat butun son bo'lmasa — RangeError.
  • countBy(items, key) — key funksiyasi bergan satr bo'yicha sanab, Map<string, number> qaytarsin.

Avval chunk ni generic'siz yozing — unknown[] qabul qilib, unknown[][] qaytarsin. Test faylda mehmonlarni stollarga bo'ling va ikkinchi stoldagi birinchi mehmon ismini katta harf bilan oling: tables[1]?.[0]?.toUpperCase(). npx tsc --pretty false nima deydi?

Yechim

unknown variantda tsc 7.0.2 test faylni to'xtatdi:

text
20-generics/list.test.ts(10,32): error TS2339: Property 'toUpperCase' does not exist on type '{}'.

{} qayerdan chiqdi? tables[1]?.[0] — unknown. ?. undan null va undefined ni olib tashladi — unknown dan qolgani {}: "null va undefined dan boshqa istalgan qiymat". Unda toUpperCase yo'q. Funksiya mehmonlar satr ekanini "unutgan" — generic bu ma'lumotni saqlaydi.

ts
// 20-generics/list.ts — har qanday ro'yxat uchun yordamchilar
export function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}

export function last<T>(items: readonly T[]): T | undefined {
  return items.at(-1);
}

// [1, 2, 3, 4, 5], 2 → [[1, 2], [3, 4], [5]]
export function chunk<T>(items: readonly T[], size: number): T[][] {
  if (!Number.isInteger(size) || size < 1) {
    throw new RangeError(`Bo'lak hajmi musbat butun son: ${size}`);
  }
  const result: T[][] = [];
  for (let i = 0; i < items.length; i += size) {
    result.push(items.slice(i, i + size));
  }
  return result;
}

// Kalit funksiyasi bo'yicha sanash: qaysi guruhda nechta element
export function countBy<T>(
  items: readonly T[],
  key: (item: T) => string,
): Map<string, number> {
  const counts = new Map<string, number>();
  for (const item of items) {
    const k = key(item);
    counts.set(k, (counts.get(k) ?? 0) + 1);
  }
  return counts;
}
ts
// 20-generics/list.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { first, last, chunk, countBy } from "./list.ts";

const guests = ["Malika", "Bobur", "Sardor", "Dilshod aka", "Ali"];

test("first va last: bo'sh ro'yxatda undefined", () => {
  assert.equal(first(guests), "Malika");
  assert.equal(last([35000, 28000]), 28000);
  assert.equal(first([]), undefined);
});

test("chunk: stollarga 4 tadan", () => {
  const tables = chunk(guests, 4);
  assert.equal(tables.length, 2);
  assert.equal(tables[1]?.[0]?.toUpperCase(), "ALI");
  assert.throws(() => chunk(guests, 0), RangeError);
});

test("countBy: buyurtmalar taom bo'yicha", () => {
  const orders = [
    { dish: "osh", table: 1 },
    { dish: "manti", table: 2 },
    { dish: "osh", table: 3 },
  ];
  const counts = countBy(orders, (o) => o.dish);
  assert.equal(counts.get("osh"), 2);
  assert.equal(counts.get("lagmon"), undefined);
});
  • items.slice(i, i + size) — T[], result esa T[][]: "T lar massivlarining massivi".
  • countBy dagi (o) => o.dish — o ning turi orders elementidan chiqarildi, siz yozmadingiz.
  • first([]) turi — undefined: bo'sh massivdan T sifatida never chiqariladi, never | undefined esa undefined.
  • tables[1]?.[0] — tashqi massiv ham, ichkisi ham noUncheckedIndexedAccess tufayli undefined bo'lishi mumkin.

npx tsc --pretty false — chiqishsiz. node --test 20-generics/list.test.ts bizda (Node 24.21.0) shunday chiqdi:

text
✔ first va last: bo'sh ro'yxatda undefined (1.8269ms)
✔ chunk: stollarga 4 tadan (1.0155ms)
✔ countBy: buyurtmalar taom bo'yicha (0.4708ms)
ℹ tests 3
ℹ suites 0
ℹ pass 3
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 357.8759

XATOLAR.md ga qo'shing: TS18046 (unknown natija), "Property 'length' does not exist on type 'T'", generic chaqiruvdagi TS2345 va {} turidagi TS2339. Keyin kurs/mashqlar papkasidan:

bash
git add 15/20-generics 15/XATOLAR.md
git commit -m "15/20: list.ts — first, last, chunk, countBy generic"

vazifalar loyihasidagi generic qadam keyingi darsda: qidiruv, saralash va taymer modullarida @template allaqachon bor, ular cheklovlar bilan .ts ga o'tadi.

11. Real ishda

  • Kutubxonalar API'si — deyarli hammasi generic: useState<T> (React), fetch javobini o'raydigan ApiResponse<T>, Promise<T>, Map<K, V>. Hujjatlardagi <T> ni o'qiy olish — kundalik ko'nikma.
  • Yordamchi funksiyalar (chunk, groupBy, uniqBy) — lodash kabi kutubxonalarda va har loyihaning utils papkasida generic bo'ladi.
  • Kod ko'rib chiqishda "bu yerda any emas, generic bo'lsin" va "bu generic keraksiz, T bitta joyda" — ikkalasi ham tez-tez yoziladigan izohlar.
  • Intervyu: "Generic nima va any dan farqi?", "Tur argumenti qachon chiqariladi?", "identity<T> yozing" — junior/middle TypeScript savollari.

Xulosa

  • Generic funksiya turni parametr qiladi: function first<T>(items: readonly T[]): T | undefined.
  • T odatda argumentlardan chiqariladi (inference). Kerak bo'lsa — first<number>(…) bilan aniq yoziladi.
  • any tur ma'lumotini o'chiradi, unknown uni har safar tekshirtiradi, generic esa kirish va chiqishni bog'lab saqlaydi.
  • Cheklovsiz T — qora quti: uning xususiyatlariga murojaat qilib bo'lmaydi (TS2339), buni cheklovlar hal qiladi.
  • T faqat natijada bo'lsa — bu tekshiruvsiz as: ishlash paytida generic'lar yo'q.

Keyingi dars: Generic cheklovlar va keyof — T extends { length: number }, K extends keyof T va bir nechta tur parametri. vazifalar dagi uch modul generic cheklovlar bilan .ts ga o'tadi.

Manbalar

  • TypeScript Handbook: "Generics" (Hello World of Generics, Working with Generic Type Variables) — typescriptlang.org/docs/handbook/2/generics.html
  • TypeScript Handbook: "More on Functions" (Generic Functions, Inference, Guidelines) — typescriptlang.org/docs/handbook/2/functions.html#generic-functions
  • TypeScript Handbook: "Type Inference" — typescriptlang.org/docs/handbook/type-inference.html
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript generics: turni parametr qilish — <T>, identity va first<T> — IlmHamroh