Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tur parametri <T>
- 2.1 Birinchi generic funksiya
- 2.2 T ni kim to'ldiradi?
- 2.3 Eng sodda generic: identity
- 2.4 T chiqarilmasa — unknown
- 3. Generic, any va unknown
- 3.1 Uchala variant yonma-yon
- 3.2 Funksiya ichida T — "qora quti"
- 4. Generic va callback
- 4.1 T parametrlar orasida bog'lanadi
- 4.2 Bir chaqiruvda T bitta
- 5. Tayyor generic turlar
- 5.1 Siz ularni allaqachon ishlatgansiz
- 5.2 Massiv metodlari ham generic
- 5.3 Bo'sh konteynerga tur argumenti
- 6. Generic arrow funksiya
- 7. TypeScript ushlamaydigan tuzoq: yolg'onchi generic
- 8. Generic qachon kerak emas?
- 9. Ko'p uchraydigan xatolar
- 9.1 Generic o'rniga any
- 9.2 Cheklovsiz T ning xususiyatiga murojaat
- 9.3 Bo'sh konteyner tur argumentisiz
- 9.4 T faqat natijada
- 9.5 Natijada undefined ni unutish
- 10. Mashqlar
- 1-mashq (oson): Turlarni ayting
- 2-mashq (o'rta): findBy ni yozing
- 3-mashq (qiyin): Amaliy tajriba — ro'yxat yordamchilari
- 11. Real ishda
- Xulosa
- Manbalar
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 TypeScriptT = numberekanini o'zi chiqaradi va natijanumber | undefinedbo'ladi.anydan 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,
anyvaunknownfarqini misolda ko'rsata olasiz. Array<T>,Map<K, V>,Promise<T>kabi tayyor generic turlarni o'qiysiz.- "Yolg'onchi generic" tuzog'ini taniysiz —
Tfaqat 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:
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"])); // MalikaIkki funksiyaning tanasi bir xil, faqat turlar farq qiladi. Ertaga buyurtmalar, stollar, bronlar uchun yana uchtasi kerak bo'ladi.
Ikkinchi urinish — any bilan bitta funksiya:
function first(items: readonly any[]): any {
return items[0];
}
const price = first([35000, 28000]);
console.log(price.toUpperCase());tsc — xatosiz. Node esa:
TypeError: price.toUpperCase is not a functionany 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
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 MalikaQatorni 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[]— "Tturidagi elementlar ro'yxati".: T | undefined— "o'shaTturidagi element yokiundefined" (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:
function first<T>(items: readonly T[]): T | undefined {
return items[0];
}
const id = first<number>([101, 102]);
console.log(id); // 101first<number>(…) — "T — bu number". Odatda shart emas: TypeScript to'g'ri chiqaradi. Lekin shunda TypeScript argumentlarni ham shu turga qarab tekshiradi:
function first<T>(items: readonly T[]): T | undefined {
return items[0];
}
const name = first<string>([1, 2]);Kompilyator:
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:
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 35000Hover'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:
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 2Hover'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:
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?
function firstUnknown(items: readonly unknown[]): unknown {
return items[0];
}
const price = firstUnknown([35000]);
price.toFixed(0);Kompilyator:
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:
function lengthOf<T>(value: T): number {
return value.length;
}Kompilyator:
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:
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:
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:
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:
function pair<T>(a: T, b: T): T[] {
return [a, b];
}
pair(35000, "Osh");Kompilyator:
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)—namening 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":
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:
const stock = new Map<string, number>();
stock.set("osh", 12);
console.log(stock.get("osh")); // 12new 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?tagsning 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:
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:
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:
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:
- Funksiya bitta aniq tur bilan ishlaydimi?
totalPrice(prices: number[])faqat sonlarni qo'shadi — ungaTkerak emas.totalPrice<T>yozsangiz, ichkarida+ishlatib bo'lmaydi (T— qora quti) va kod faqat murakkablashadi. Tkamida ikki joyni bog'laydimi?first(items: T[]): T— parametr va natijani bog'laydi, foydali.log<T>(value: T): void—Tbitta joyda, natijada yo'q. Bulog(value: unknown): voidbilan 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
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:constva literal argument,T = true.y—number | undefined:T = number, bo'sh ro'yxat uchunundefined.z—number[]:mapdaUcallback 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.
const menu = [
{ name: "Osh", price: 35000 },
{ name: "Manti", price: 30000 },
];
const found = findBy(menu, (d) => d.price < 32000);
console.log(found?.name); // MantiYechim
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)); // undefinedT = { name: string; price: number }—menudan chiqarildi,dham shu tur.found?.name—foundundefinedbo'lishi mumkin,?.buni hisobga oladi.- Natija turi
T | undefined—anybo'lgandafound.namejim 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)valast(items)— element yokiundefined. Ishora:items.at(-1)— oxirgi element (Massiv: yaratish va elementga murojaat).chunk(items, size)— ro'yxatnisizetadan bo'laklarga bo'lsin:[1, 2, 3, 4, 5], 2 →[[1, 2], [3, 4], [5]].sizemusbat butun son bo'lmasa —RangeError.countBy(items, key)—keyfunksiyasi 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:
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.
// 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;
}// 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[],resultesaT[][]: "Tlar massivlarining massivi".countBydagi(o) => o.dish—oning turiorderselementidan chiqarildi, siz yozmadingiz.first([])turi —undefined: bo'sh massivdanTsifatidaneverchiqariladi,never | undefinedesaundefined.tables[1]?.[0]— tashqi massiv ham, ichkisi hamnoUncheckedIndexedAccesstufayliundefinedbo'lishi mumkin.
npx tsc --pretty false — chiqishsiz. node --test 20-generics/list.test.ts bizda (Node 24.21.0) shunday chiqdi:
✔ 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.8759XATOLAR.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:
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),fetchjavobini o'raydiganApiResponse<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 loyihaningutilspapkasida generic bo'ladi. - Kod ko'rib chiqishda "bu yerda
anyemas, generic bo'lsin" va "bu generic keraksiz,Tbitta joyda" — ikkalasi ham tez-tez yoziladigan izohlar. - Intervyu: "Generic nima va
anydan 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. Todatda argumentlardan chiqariladi (inference). Kerak bo'lsa —first<number>(…)bilan aniq yoziladi.anytur ma'lumotini o'chiradi,unknownuni 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. Tfaqat natijada bo'lsa — bu tekshiruvsizas: 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
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!