Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. Massiv turi
- 2.1 number[] — "sonlar massivi"
- 2.2 Array<number> — o'sha tur, boshqa yozuv
- 2.3 Aralash massiv qanday chiqariladi?
- 2.4 Bo'sh massivga tur yozing
- 3. readonly massiv
- 3.1 O'zgartirib bo'lmaydigan ro'yxat
- 3.2 Parametrda readonly — va'da
- 3.3 readonly faqat tekshiruvda yashaydi
- 4. Tuple
- 4.1 Aniq uzunlik, aniq o'rinlar
- 4.2 Tuple o'zi chiqarilmaydi
- 4.3 Nomlangan tuple elementlari
- 4.4 Ixtiyoriy element
- 4.5 Rest element: "qolgani — shu turdagi"
- 4.6 Tuple tuzog'i: push ruxsat etilgan
- 5. as const: massivni aniq qilib qotirish
- 6. TypeScript ushlamaydigan tuzoq: mavjud bo'lmagan indeks
- 7. Massivmi yoki tuple?
- 8. Ko'p uchraydigan xatolar
- 8.1 [] ni "massiv" turi deb yozish
- 8.2 Array ni ichsiz yozish
- 8.3 string | number[] qavssiz
- 8.4 Funksiyadan tuple qaytarib, natija turini yozmaslik
- 8.5 Indeksga ko'r-ko'rona ishonish
- 9. Mashqlar
- 1-mashq (oson): Turlarni ayting
- 2-mashq (o'rta): minMax ni tuzating
- 3-mashq (qiyin): Amaliy tajriba — bron vaqtlari
- 10. Real ishda
- Xulosa
- Manbalar
TypeScript massiv va tuple turlari: number[], readonly va as const
Qisqacha: Massiv turi — bir xil turdagi elementlar ro'yxati:
number[]yokiArray<number>(ikkalasi bir xil).readonly number[]— o'zgartirib bo'lmaydigan massiv. Tuple — uzunligi va har o'rnining turi aniq bo'lgan massiv:[string, number]— "avval nom, keyin narx".as constesa massivni o'zgarmas tuple'ga aylantiradi va qiymatlarni aniq saqlaydi.
Bu darsda
- Massiv turini ikki xil yozasiz va qaysi biri qachon qulayligini bilasiz.
readonlymassiv bilan funksiyaga "men bu massivni o'zgartirmayman" degan va'da berasiz.- Tuple yozasiz: oddiy, nomlangan, ixtiyoriy va rest elementli.
as constnima qilishini va o'tgan darsdagi literal turlar bilan bog'liqligini tushuntira olasiz.- TypeScript ushlamaydigan indeks tuzog'ini taniysiz va undan saqlanasiz.
Oldin bilishingiz kerak: Tur annotatsiyasi va tur chiqarish, Massiv: yaratish va elementga murojaat, Massiv destructuring.
1. Nega bu kerak?
O'tgan darsda TypeScript turni qiymatdan o'zi chiqarishini ko'rdik. Endi massivlarga o'tamiz — «Bahor» kodining katta qismi aynan ro'yxatlar: menyu, narxlar, buyurtmalar, bronlar.
Sardor kunlik tushumni hisoblayapti. Narxlardan biri jadvaldan nusxa olinganda satr bo'lib qolgan:
const prices = [35000, "28 000", 30000];
const sum = prices.reduce((total, p) => total + p, 0);
console.log(sum); // 3500028 00030000Kutilgan natija — 93 000. Chiqqani — uzun g'alati satr. 35000 + "28 000" satr berdi, keyin unga 30000 yopishtirildi. JavaScript massivga istalgan turdagi narsani solishga ruxsat beradi va hech narsa demaydi.
Ikkinchi muammo nozikroq. Jasur aka eng arzon taomni so'radi va Sardor funksiya yozdi:
function cheapest() {
return ["Ko'k choy", 5000];
}
const result = cheapest();
console.log(result[1]); // 5000result[0] — nommi yoki narxmi? Buni faqat funksiya ichiga qarab bilasiz. Uch oydan keyin kimdir tartibni almashtirib qo'ysa ([5000, "Ko'k choy"]), hamma chaqiruvlar jim buziladi.
Bu darsda ikkala muammoni ham turlar bilan hal qilamiz: birinchisini massiv turi, ikkinchisini tuple bilan.
2. Massiv turi
2.1 number[] — "sonlar massivi"
Yozuv sizga JSDoc darsidan tanish: element turi va kvadrat qavslar.
const prices: number[] = [35000, 28000, 30000];
const dishes = ["Osh", "Manti", "Lag'mon"];
const total = prices.reduce((sum, p) => sum + p, 0);
console.log(total, dishes.length); // 93000 3dishes ga tur yozmadik — TypeScript uni qiymatdan chiqardi: string[]. Hover'da const dishes: string[] ko'rinadi. reduce dagi sum va p ham kontekstdan chiqarildi — ikkalasi son.
Endi «Nega bu kerak?» bo'limidagi ikki xatoni qilib ko'ramiz:
const prices: number[] = [35000, "28 000", 30000];
const dishes = ["Osh", "Manti"];
dishes.push(35000);Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.
TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.Birinchi xabar: "string ni number ga berib bo'lmaydi" — tsc aynan "28 000" elementini ko'rsatadi, butun massivni emas. Ikkinchisi yangi: "number turidagi argumentni string turidagi parametrga berib bo'lmaydi". dishes — string[], demak uning push metodi faqat satr qabul qiladi. Bir marta string[] bo'lgan massivga son kira olmaydi.
2.2 Array<number> — o'sha tur, boshqa yozuv
const prices: Array<number> = [35000, 28000];
const names: string[] = ["Malika", "Bobur"];
console.log(prices.length + names.length); // 4Array<number> va number[] — aynan bir xil tur. Burchak qavs <…> "ichida nima bor" degani: JSDoc darsidagi Set<number> ("sonlar to'plami") kabi. Bu yozuv generic deyiladi — turning ichiga boshqa tur beriladi. Generic'larni o'zingiz yozishni Generics: turni parametr qilish darsida o'rganasiz. Hozircha uni o'qiy olish yetarli.
Qaysi birini yozish kerak? Ko'pchilik jamoalarda qisqasi — number[]. Element turi murakkab bo'lsa, ba'zan Array<…> o'qishga osonroq:
| Ma'nosi | Qisqa yozuv | Generic yozuv |
|---|---|---|
| sonlar massivi | number[] |
Array<number> |
| son yoki satrlar massivi | (string | number)[] |
Array<string | number> |
| o'zgarmas satrlar massivi | readonly string[] |
ReadonlyArray<string> |
Ikkinchi qatordagi qavsga e'tibor bering. U muhim:
const mixed: string | number[] = ["Osh", 35000];Kompilyator:
TS2322: Type '(string | number)[]' is not assignable to type 'string | number[]'.
Type '(string | number)[]' is not assignable to type 'number[]'.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.Qavssiz string | number[] — "satr yoki sonlar massivi". Ya'ni yo bitta satr, yo faqat sonlardan iborat massiv. Aralash massiv bunga mos emas. To'rt qatorli zanjir pastga qarab torayib boradi: eng pastki qator — eng aniq sabab, "massiv ichidagi satrni songa berib bo'lmaydi". Qoida: | li element turini massivga aylantirsangiz — qavsga oling: (string | number)[]. Yoki adashmaslik uchun generic yozuvni tanlang.
2.3 Aralash massiv qanday chiqariladi?
const row = ["Osh", 35000];
console.log(row); // [ 'Osh', 35000 ]Hover: const row: (string | number)[]. TypeScript har bir element turini yig'ib, ulardan birlashma (union) yasadi. U row[0] satr, row[1] esa son ekanini eslab qolmaydi: uning uchun har bir element "satr yoki son". Bu tartibni eslab qoladigan tur — tuple, uni «Tuple» bo'limida ko'ramiz.
2.4 Bo'sh massivga tur yozing
Massiv bo'sh boshlansa, TypeScript element turini bilmaydi:
const orderIds = [];
orderIds.push(101);
function lastOrders() {
return orderIds;
}Kompilyator:
TS7034: Variable 'orderIds' implicitly has type 'any[]' in some locations where its type cannot be determined.
TS7005: Variable 'orderIds' implicitly has an 'any[]' type.Tarjimasi: "orderIds ba'zi joylarda turi aniqlab bo'lmaydigan any[] turini yashirincha oldi". TypeScript bo'sh massivning keyingi push larini bir fayl ichida kuzatishga harakat qiladi. Lekin massiv funksiyaga "chiqib ketsa", u taslim bo'ladi va any[] — "istalgan narsalar massivi" — deydi. strict rejim esa yashirin any ga ruxsat bermaydi.
Tuzatish oddiy — bo'sh massivga doim tur yozing. Bu o'tgan darsdagi "qiymatsiz e'lon — tur yozing" qoidasining o'zi: bo'sh massivda ham element qiymati yo'q.
const orderIds: number[] = [];
orderIds.push(101);
orderIds.push(102);
console.log(orderIds); // [ 101, 102 ]Tekshirib ko'ring:
const scores = [4.5, 5, 3];— hover'da qaysi tur?const tags = ["achchiq", 1, true];chi?
Javob
const scores: number[] — butun va kasr sonlar bir xil tur. const tags: (string | number | boolean)[] — uch xil element, TypeScript ulardan birlashma yasadi. Ikkinchi holat odatda xato belgisi: bitta massivda turli ma'nodagi narsalar aralashgan. Ularni obyekt yoki tuple qilish to'g'riroq.
3. readonly massiv
3.1 O'zgartirib bo'lmaydigan ro'yxat
Menyu kun davomida o'zgarmaydi. Uni hech kim tasodifan buzmasligi uchun turga readonly (faqat o'qish uchun) so'zini qo'shamiz:
const menu: readonly string[] = ["Osh", "Manti"];
menu.push("Lag'mon");
menu[0] = "Palov";
menu.sort();Kompilyator:
TS2339: Property 'push' does not exist on type 'readonly string[]'.
TS2542: Index signature in type 'readonly string[]' only permits reading.
TS2339: Property 'sort' does not exist on type 'readonly string[]'.pushvasortyo'q: "readonly string[]turidapushxususiyati yo'q". TypeScript massivni o'zgartiradigan hamma metodlarni (push,pop,splice,sort,reverse…) bu turdan olib tashlagan.menu[0] = …— "indeks orqali faqat o'qish mumkin". Indeks imzosi (index signature) —menu[0],menu[1]kabi raqam bilan murojaat qilish qoidasi.
O'qiydigan va yangi massiv qaytaradigan metodlar esa joyida: map, filter, slice va nusxa bilan ishlaydiganlar — toSorted, toReversed, with:
const menu: readonly string[] = ["Osh", "Manti", "Lag'mon"];
const sorted = menu.toSorted();
console.log(sorted); // [ "Lag'mon", 'Manti', 'Osh' ]
console.log(menu); // [ 'Osh', 'Manti', "Lag'mon" ]Asl menyu o'zgarmadi. sorted esa oddiy (o'zgartirsa bo'ladigan) string[] — u yangi massiv.
3.2 Parametrda readonly — va'da
readonly ning eng foydali joyi — funksiya parametri:
function totalOf(prices: readonly number[]): number {
return prices.reduce((sum, p) => sum + p, 0);
}
const today = [35000, 28000];
console.log(totalOf(today)); // 63000readonly number[] parametr chaqiruvchiga aytadi: "massivingizni beraveringiz, men uni o'zgartirmayman". Oddiy number[] ni ham bemalol berish mumkin — today o'zgaruvchan massiv, lekin funksiya uni faqat o'qiydi. Funksiya ichida prices.push(…) deb yozsangiz, tsc darhol to'xtatadi.
Teskarisi ishlamaydi. O'zgarmas massivni "o'zgartiraman" degan funksiyaga berib bo'lmaydi:
function sortPrices(prices: number[]) {
return prices.sort();
}
const fixed: readonly number[] = [35000, 5000];
sortPrices(fixed);Kompilyator:
TS4104: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.Tarjimasi: "readonly number[] turi faqat o'qish uchun, uni o'zgaruvchan (mutable) number[] turiga berib bo'lmaydi". sortPrices massivni joyida saralaydi (Element qo'shish va olib tashlash darsidagi mutatsiya) — readonly va'dasi buzilardi.
Qoida: massivni faqat o'qiydigan funksiyada parametrni readonly qiling. Shunda funksiya har ikki xil massivni ham qabul qiladi.
3.3 readonly faqat tekshiruvda yashaydi
Bu muhim: readonly — tur, JavaScript emas. tsc 7.0.2 const menu: readonly string[] = ["Osh", "Manti"]; qatorini shunday yozadi:
const menu = ["Osh", "Manti"];Ishlash paytida bu oddiy massiv. Kimdir uni turlarsiz JavaScript fayldan o'zgartirsa, hech kim to'xtatmaydi. Ishlash paytida ham himoya kerak bo'lsa — Object.freeze:
const menu = Object.freeze(["Osh", "Manti"]);
console.log(Object.isFrozen(menu)); // trueHover: const menu: readonly string[]. Object.freeze ikkalasini beradi: TypeScript turini (readonly) va ishlash paytidagi himoyani. Odatda esa readonly turning o'zi yetarli: tekshiruvdan o'tgan kod uni buzmaydi.
Tekshirib ko'ring:
function firstDish(menu: readonly string[]) { return menu[0]; }— bu funksiyaga["Osh", "Manti"]oddiy massivini berish mumkinmi?
Javob
Mumkin. readonly parametr — funksiyaning va'dasi: "o'zgartirmayman". Oddiy massivni o'qish uchun berishda xavf yo'q. Taqiqlangan yo'nalish — teskarisi: readonly massivni o'zgaruvchan string[] kutgan funksiyaga berish (TS4104).
4. Tuple
4.1 Aniq uzunlik, aniq o'rinlar
Tuple (o'qilishi "tapl") — uzunligi aniq va har bir o'rnining o'z turi bor massiv. Kunlik o'xshatish — chek qatori: avval taom nomi, keyin narxi. O'rinlar almashsa, chek ma'nosiz bo'ladi.
const item: [string, number] = ["Osh", 35000];
console.log(`${item[0]}: ${item[1]} so'm`); // Osh: 35000 so'm[string, number] — "ikki elementli massiv: 0-o'rinda satr, 1-o'rinda son". Endi TypeScript item[0] ni string, item[1] ni number deb biladi — (string | number)[] dagi kabi aralashtirmaydi.
Tuple uch xil xatoni ushlaydi — tartib, uzunlik va mavjud bo'lmagan o'rin:
const item: [string, number] = [35000, "Osh"];
const short: [string, number] = ["Osh"];
const pair: [string, number] = ["Osh", 35000];
console.log(pair[2]);Kompilyator:
TS2322: Type 'number' is not assignable to type 'string'.
TS2322: Type 'string' is not assignable to type 'number'.
TS2322: Type '[string]' is not assignable to type '[string, number]'.
Source has 1 element(s) but target requires 2.
TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.- Birinchi ikkitasi — tartib almashgan: 0-o'ringa son, 1-o'ringa satr berilgan.
- Uchinchisi: "manbada 1 ta element, maqsad esa 2 ta talab qiladi".
- To'rtinchisi: "uzunligi 2 bo'lgan tuple'da 2-indeksli element yo'q". Indekslar 0 dan boshlanadi — 0 va 1 bor, 2 yo'q. Oddiy massivda bu xato chiqmasdi.
4.2 Tuple o'zi chiqarilmaydi
«Nega bu kerak?» bo'limidagi cheapest ni TypeScript'ga ko'chiramiz:
function cheapest() {
return ["Ko'k choy", 5000];
}
const [name, price] = cheapest();
const doubled = price * 2;Kompilyator:
TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.Tarjimasi: "Arifmetik amalning chap tomoni any, number, bigint yoki enum turida bo'lishi kerak". Nega price son emas? Chunki TypeScript ["Ko'k choy", 5000] dan tuple emas, oddiy massiv chiqardi: (string | number)[] (aralash massiv kabi). Destructuring'dagi price ham "satr yoki son" bo'lib qoldi, satrni esa 2 ga ko'paytirib bo'lmaydi. (bigint — juda katta butun sonlar turi, enum — enum va uning muqobillari darsida.)
Tuzatish — natija turini yozish. Bu o'tgan darsdagi qoida bilan bir xil: TypeScript niyatingizni bilmaydi, siz aytasiz:
function cheapest(): [string, number] {
return ["Ko'k choy", 5000];
}
const [name, price] = cheapest();
console.log(name, price * 2); // Ko'k choy 10000Endi name — string, price — number. Massiv destructuring tuple bilan ayniqsa qulay: o'rinlarga darhol tushunarli nom berasiz.
4.3 Nomlangan tuple elementlari
[string, number] dan har o'rin nimani anglatishi ko'rinmaydi. Ularga nom (label) berish mumkin:
function workingHours(): [open: number, close: number] {
return [7, 23];
}
const [from, to] = workingHours();
console.log(`${from}:00–${to}:00`); // 7:00–23:00open va close — faqat hujjat. Ular hover'da va chaqiruvda maslahat sifatida ko'rinadi ([open: number, close: number]), lekin destructuring nomlariga ta'sir qilmaydi: biz from va to deb oldik. Ishlash paytida ham ular yo'q — bu oddiy [7, 23] massivi.
vazifalar loyihasida ham aynan shunday tur bor (qidiruv.ts, Generic cheklovlar va keyof qadamida .ts ga o'tadi):
/** Asl matndagi [boshi, oxiri) — oxiri kirmaydi */
export type Oraliq = [boshi: number, oxiri: number];type Oraliq = … — turga nom berish: endi har joyda uzun yozuv o'rniga Oraliq deyiladi. Bu yozuvni type va interface darsida to'liq o'rganamiz. Hozir faqat o'ng tomonga qarang — nomlangan tuple: qidiruvda topilgan bo'lakning boshi va oxiri.
4.4 Ixtiyoriy element
Buyurtma qatorida izoh bo'lishi ham, bo'lmasligi ham mumkin. Ixtiyoriy o'rin ? bilan belgilanadi:
const plain: [dish: string, qty: number, note?: string] = ["Osh", 2];
const custom: [dish: string, qty: number, note?: string] = [
"Manti",
3,
"achchiqsiz",
];
console.log(plain.length, custom.length); // 2 3
console.log(plain[2] ?? "izohsiz"); // izohsizHover'da plain.length turi — 2 | 3: "uzunligi 2 yoki 3". plain[2] turi esa string | undefined — izoh bo'lmasligi ham mumkin, shuning uchun ?? bilan standart matn berdik. Ixtiyoriy elementlar faqat oxirida turadi: [note?: string, dish: string] yozib bo'lmaydi.
4.5 Rest element: "qolgani — shu turdagi"
Narxlar tarixi: avval taom nomi, keyin nechta bo'lsa ham narx. Tuple ichida ... (rest) ishlatiladi — Spread va rest darsidagi uch nuqta:
const history: [string, ...number[]] = ["Osh", 30000, 32000, 35000];
const [dish, ...prices] = history;
console.log(dish, prices.length); // Osh 3
console.log(Math.max(...prices)); // 35000[string, ...number[]] — "birinchisi satr, qolganlari — istalgancha son (nol ta ham)". ["Osh"] ham mos keladi. Destructuring'da prices — number[]. Rest o'rta yoki boshda ham bo'lishi mumkin: [...string[], number] — "oxirgisi son, oldingilari satrlar".
4.6 Tuple tuzog'i: push ruxsat etilgan
Tuple uzunligi tekshiriladi, lekin faqat yaratilganda. Keyin esa — kutilmagan narsa:
const pair: [string, number] = ["Osh", 35000];
pair.push(5000);
const len: 2 = pair.length;
console.log(len); // 3
console.log(pair); // [ 'Osh', 35000, 5000 ]tsc hech qanday xato bermadi. Turga ko'ra pair.length — aniq 2 (literal tur), haqiqatda esa 3. Sababi: tuple — massiv, massivda esa push metodi bor. TypeScript tuple'ning push iga ham element turini (string | number) tekshiradi, lekin uzunlik o'zgarishini kuzatmaydi.
Himoya — readonly tuple:
const pair: readonly [string, number] = ["Osh", 35000];
pair.push(5000);Kompilyator:
TS2339: Property 'push' does not exist on type 'readonly [string, number]'.TypeScript aytyapti: «readonly [string, number] turida push xususiyati yo'q». Faqat o'qiladigan tuple'da o'zgartiruvchi metodlar umuman yo'q — push, pop, sort ham.
Qoida: tuple'ni o'zgartirmaydigan bo'lsangiz (ko'pincha shunday), uni readonly qiling.
Tekshirib ko'ring: Qaysi biri
[string, ...number[]]turiga mos:["Manti"],[30000, "Manti"],["Manti", 28000, 30000]?
Javob
["Manti"] va ["Manti", 28000, 30000] mos: birinchi o'rinda satr, keyin nol yoki ko'p son. [30000, "Manti"] mos emas — birinchi o'rinda son turibdi, tartib muhim.
5. as const: massivni aniq qilib qotirish
O'tgan darsda const city = "Toshkent" ning turi "Toshkent" bo'lishini, lekin obyekt ichida qiymatlar kengayishini ko'rdik. Massivda ham xuddi shunday: const sizes = ["kichik", "o'rta", "katta"] — string[]. Qiymatlar unutiladi.
as const ("o'zgarmas sifatida") TypeScript'ga aytadi: "bu qiymatni aynan shunday eslab qol — kengaytirma va o'zgartirishga ruxsat berma":
const sizes = ["kichik", "o'rta", "katta"] as const;
const dish = ["Osh", 35000] as const;
console.log(sizes.length, dish[1]); // 3 35000| Kod | Hover'da |
|---|---|
["kichik", "o'rta", "katta"] |
string[] |
["kichik", "o'rta", "katta"] as const |
readonly ["kichik", "o'rta", "katta"] |
["Osh", 35000] |
(string | number)[] |
["Osh", 35000] as const |
readonly ["Osh", 35000] |
as const uch ish qiladi:
- Massivni tuple qiladi — uzunlik va o'rinlar eslab qolinadi.
- Elementlarni literal tur qiladi —
"kichik",35000,stringvanumberemas. - Hammasini
readonlyqiladi:
const sizes = ["kichik", "o'rta", "katta"] as const;
sizes.push("juda katta");Kompilyator:
TS2339: Property 'push' does not exist on type 'readonly ["kichik", "o'rta", "katta"]'.Qachon kerak? O'zgarmaydigan, oldindan ma'lum ro'yxatlarda: porsiya o'lchamlari, buyurtma holatlari, hafta kunlari. Bunday ro'yxatdan "faqat shu uch qiymatdan biri" degan tur yasash mumkin — buni Union va literal turlar darsida qilamiz. Yana bir eslatma: as const ham faqat tur. Ishlash paytida massiv oddiy bo'lib qoladi, Object.freeze dagi himoya yo'q. Masalan, tsc uni const sizes = ["kichik", "o'rta", "katta"]; qilib yozadi.
Tekshirib ko'ring:
const hours = [10, 22] as const;—hours[0]ning turi qanday?hours[0] = 9yozsa bo'ladimi?
Javob
hours[0] turi — 10 (literal tur), chunki as const qiymatlarni aniq saqlaydi. hours[0] = 9 — xato: as const massivni readonly qiladi, indeks orqali yozib bo'lmaydi. Agar yozib bo'lganda ham, 9 qiymati 10 turiga mos kelmasdi.
6. TypeScript ushlamaydigan tuzoq: mavjud bo'lmagan indeks
Tuple'da pair[2] xato edi. Oddiy massivda-chi?
const prices = [35000, 28000];
const p = prices[5];
console.log(p.toFixed(0));tsc — xatosiz. Node esa:
TypeError: Cannot read properties of undefined (reading 'toFixed')Hover'da const p: number — TypeScript prices[5] ni son deb hisobladi. Massivda 2 ta element, 5-indeksda hech narsa yo'q, JavaScript esa bunday holatda undefined qaytaradi (Massiv: yaratish va elementga murojaat). Ya'ni tur yolg'on gapirdi.
Nega TypeScript shunday qiladi? Massiv uzunligi ishlash paytida o'zgaradi, kompilyator uni bilmaydi. Har prices[i] ni "number | undefined" desa, eng oddiy sikllar ham tekshiruvga to'lib ketardi. TypeScript jamoasi standart holatda qulaylikni tanlagan.
Lekin buni yoqadigan maxsus bayroq bor — noUncheckedIndexedAccess ("tekshirilmagan indeks murojaati yo'q"). Uni blokning birinchi qatoridagi sozlama bilan yoqib ko'ramiz:
// @ts-options: {"noUncheckedIndexedAccess": true}
const prices = [35000, 28000];
const p = prices[5];
console.log(p.toFixed(0));Kompilyator:
TS18048: 'p' is possibly 'undefined'.Tarjimasi: "p undefined bo'lishi mumkin". Endi prices[5] ning turi — number | undefined, va TypeScript tekshiruvsiz ishlatishga yo'l qo'ymaydi. Tuzatish — JSDoc darsidagi kabi, turni toraytirish:
// @ts-options: {"noUncheckedIndexedAccess": true}
const prices = [35000, 28000];
const p = prices[5];
if (p === undefined) {
console.log("Bunday narx yo'q"); // Bunday narx yo'q
} else {
console.log(p.toFixed(0));
}Bu bayroq haqida uch fakt:
strictga kirmaydi — alohida yoqiladi. Saytimizdagi bloklar va Playground'da u standart holatda o'chiq.tsc --init(TypeScript 7) uni yoqib qo'yadi — yangitsconfig.jsonda"noUncheckedIndexedAccess": trueqatori bor. Mashqlar papkangizda ham yoqilgan.for...of,map,forEachga ta'sir qilmaydi — ular faqat mavjud elementlar bo'ylab yuradi.
vazifalar ham uni yoqadi (Strict bayroqlar oilasi qadamida) va qidiruv.ts da shunday tekshiruvlar paydo bo'ladi: const birinchi = joylar[joy]; if (birinchi === undefined) …. Bayroqni va uning "narxini" o'sha darsda to'liq ko'ramiz.
7. Massivmi yoki tuple?
Tanlash uchun bitta savol yetadi: har bir o'rinning o'z ma'nosi bormi?
flowchart TD
A["Bir nechta qiymat"] --> B{"Har o'rinning<br/>o'z ma'nosi bormi?"}
B -- "yo'q, hammasi bir xil narsa" --> C["Massiv: number[]"]
B -- "ha: nom, narx, ..." --> D{"Elementlar 3 tadan ko'pmi?"}
D -- "yo'q" --> E["Tuple: [string, number]"]
D -- "ha" --> F["Obyekt: { name, price }"]
C --> G{"O'zgartirilmaydimi?"}
E --> G
G -- "ha" --> H["readonly yoki as const"]Menyu narxlari — hammasi "narx", demak massiv. "Nom va narx" — ikki xil ma'no, demak tuple. Lekin o'rinlar ko'payib ketsa ([string, number, string, boolean, number]), [3] nima ekanini hech kim eslay olmaydi — unda nomli maydonlari bor obyekt yaxshiroq (Obyekt turlari). Tuple — qisqa, 2–3 o'rinli juftliklar uchun.
8. Ko'p uchraydigan xatolar
8.1 [] ni "massiv" turi deb yozish
let names: [] = [];
names.push("Ali");Kompilyator:
TS2345: Argument of type '"Ali"' is not assignable to parameter of type 'never'.[] turi — "massiv" emas, bo'sh tuple: nol elementli. Unga hech narsa qo'shib bo'lmaydi, shuning uchun push parametri — never ("hech qanday qiymat bo'la olmaydi"; never haqida keyinroq). Tuzatish: element turini yozing — let names: string[] = [];.
8.2 Array ni ichsiz yozish
let list: Array = [];Kompilyator:
TS2314: Generic type 'Array<T>' requires 1 type argument(s).Tarjimasi: "Array<T> generic turi 1 ta tur argumentini talab qiladi". T — "bu yerga tur qo'yiladi" degan joy. Tuzatish: Array<string> yoki string[].
8.3 string | number[] qavssiz
«Array<number> — o'sha tur, boshqa yozuv» bo'limidagi to'rt qatorli xabar. Tuzatish: (string | number)[].
8.4 Funksiyadan tuple qaytarib, natija turini yozmaslik
return ["Ko'k choy", 5000] — tuple emas, (string | number)[]. Tuzatish: natija turi : [string, number] yoki as const.
8.5 Indeksga ko'r-ko'rona ishonish
prices[i] — number, lekin undefined bo'lishi mumkin. Tuzatish: uzunlikni yoki undefined ni tekshiring, loyihada noUncheckedIndexedAccess ni yoqing.
9. Mashqlar
1-mashq (oson): Turlarni ayting
const sizes = ["S", "M", "L"] as const;
const pair: [string, number] = ["Somsa", 8000];
const ids: number[] = [];
console.log(sizes.length, pair.length, ids.length); // 3 2 0sizes.length turi (literal): [:3]. pair.length turi: [:2]. Bayroqsiz ids[0] turi: .
Yechim
as const tuple yasaydi, tuple uzunligi esa literal tur: 3. pair — ikki elementli tuple, length turi 2. ids[0] — number: noUncheckedIndexedAccess siz TypeScript bo'sh massivning ham elementini son deb hisoblaydi (garchi haqiqatda undefined bo'lsa ham). Bayroq yoqilsa — number | undefined.
2-mashq (o'rta): minMax ni tuzating
Bu funksiya tsc dan xatosiz o'tadi, lekin bo'sh massivda jim NaN beradi:
function minMax(prices: number[]) {
let min = prices[0];
let max = prices[0];
for (const p of prices) {
if (p < min) min = p;
if (p > max) max = p;
}
return [min, max];
}
const [low, high] = minMax([]);
console.log(high - low); // NaNUchta o'zgarish qiling: (1) parametr readonly bo'lsin — funksiya massivni o'zgartirmaydi; (2) natija nomlangan tuple bo'lsin: [min: number, max: number]; (3) bo'sh massivda RangeError tashlansin. Ishora: bo'sh massivni prices.length === 0 bilan tekshirish mumkin, lekin noUncheckedIndexedAccess bilan ham ishlaydigan yo'l — prices[0] ni o'zgaruvchiga olib, undefined ni tekshirish.
Yechim
// @ts-options: {"noUncheckedIndexedAccess": true}
function minMax(
prices: readonly number[],
): [min: number, max: number] {
const first = prices[0];
if (first === undefined) {
throw new RangeError("Narxlar ro'yxati bo'sh");
}
let min = first;
let max = first;
for (const p of prices) {
if (p < min) min = p;
if (p > max) max = p;
}
return [min, max];
}
const [low, high] = minMax([35000, 28000, 30000, 5000]);
console.log(low, high); // 5000 35000readonly number[]— oddiy massiv ham,as constro'yxat ham beriladi.- Natija turi tuple'ni majburiy qildi: usiz
[min, max]—number[], hover'da o'rinlar nomi ham ko'rinmasdi. firstni tekshirdik —noUncheckedIndexedAccessyoqilgan bo'lsa hamtsctoza (biz uni blokning birinchi qatorida yoqdik).prices.length === 0bilan esa bayroq yoqilgandaprices[0]hali hamnumber | undefinedbo'lib qolardi: TypeScript uzunlik tekshiruvidan indeksni toraytirmaydi.
3-mashq (qiyin): Amaliy tajriba — bron vaqtlari
Mashq o'tgan darsda tayyorlangan kurs/mashqlar/15/ papkasida bajariladi. U yerdagi tsconfig.json da noUncheckedIndexedAccess yoqilgan. 04-massiv-tuple/booking.ts faylini yarating:
parseTime(text)—"19:30"→[19, 30], natija turi[hour: number, minute: number]. Buzuq matn ("19","yetti:30") —RangeError.isBookable(time)— bron 10:00 dan 22:00 gacha (22:00 ham mumkin). Parametr — o'zgarmas ikki sonli tuple.totalPeople(bookings)—[mehmon, odamlar soni]juftliklari ro'yxatidan jami odam. Parametr — o'zgarmas.
Ishora: text.split(":").map(Number) — satrlar massivini sonlar massiviga aylantiradi; Number("yetti") — NaN, uni Number.isNaN bilan tekshirasiz.
Avval birinchi variantni — tekshiruvsiz destructuring bilan — yozib, npx tsc --pretty false ni ishga tushiring:
// 04-massiv-tuple/booking.ts — «Bahor» bronlari
export function parseTime(
text: string,
): [hour: number, minute: number] {
const [hour, minute] = text.split(":").map(Number);
return [hour, minute];
}Keyin 04-massiv-tuple/booking.test.ts da testlar yozing. Nimalarni tekshirish kerak: to'g'ri vaqt va ikki buzuq vaqt; 10:00, 22:00, 22:01 va 09:59 chegaralari; bronlar yig'indisi, bo'sh ro'yxat ham.
Yechim
Birinchi variantda tsc shunday dedi:
04-massiv-tuple/booking.ts(6,11): error TS2322: Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.
04-massiv-tuple/booking.ts(6,17): error TS2322: Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.Bu noUncheckedIndexedAccess ishi: "19".split(":") — bitta elementli massiv, minute esa undefined. Bayroq bo'lmaganda tsc jim turar, funksiya [19, undefined] qaytarardi va isBookable NaN bilan solishtirib, false berardi — sababsiz "bron mumkin emas".
// 04-massiv-tuple/booking.ts — «Bahor» bronlari
export type Booking = readonly [guest: string, people: number];
// "19:30" → [19, 30]; buzuq matn — RangeError
export function parseTime(
text: string,
): [hour: number, minute: number] {
const [hour, minute] = text.split(":").map(Number);
if (hour === undefined || minute === undefined) {
throw new RangeError(`Vaqt "SS:DD" bo'lsin: ${text}`);
}
if (Number.isNaN(hour) || Number.isNaN(minute)) {
throw new RangeError(`Vaqt "SS:DD" bo'lsin: ${text}`);
}
return [hour, minute];
}
// Bron 10:00 dan 22:00 gacha (22:00 ham mumkin)
export function isBookable(time: readonly [number, number]): boolean {
const minutes = time[0] * 60 + time[1];
return minutes >= 10 * 60 && minutes <= 22 * 60;
}
export function totalPeople(bookings: readonly Booking[]): number {
let sum = 0;
for (const [, people] of bookings) {
sum += people;
}
return sum;
}Booking — juftlik turiga nom (type, xuddi Oraliq kabi). readonly Booking[] — "o'zgarmas juftliklarning o'zgarmas ro'yxati". for (const [, people] of …) — destructuring'da birinchi o'rinni vergul bilan o'tkazib yubordik. Tuple indekslari (time[0], time[1]) bayroq yoqilgan bo'lsa ham number — tuple'ning uzunligi aniq, undefined bo'lishi mumkin emas.
// 04-massiv-tuple/booking.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { parseTime, isBookable, totalPeople } from "./booking.ts";
test("parseTime: matndan tuple", () => {
assert.deepEqual(parseTime("19:30"), [19, 30]);
});
test("parseTime: buzuq matn — RangeError", () => {
assert.throws(() => parseTime("19"), RangeError);
assert.throws(() => parseTime("yetti:30"), RangeError);
});
test("isBookable: 10:00–22:00 chegaralari", () => {
assert.equal(isBookable([10, 0]), true);
assert.equal(isBookable([22, 0]), true);
assert.equal(isBookable([22, 1]), false);
assert.equal(isBookable(parseTime("09:59")), false);
});
test("totalPeople: bronlardagi odamlar", () => {
const today = [
["Dilshod aka", 4],
["Malika", 2],
] as const;
assert.equal(totalPeople(today), 6);
assert.equal(totalPeople([]), 0);
});today — as const: o'zgarmas, literal tuple'lar ro'yxati. U readonly Booking[] ga mos keladi. Agar totalPeople parametrini oddiy [string, number][] qilsangiz, tsc shu qatorni to'xtatadi:
04-massiv-tuple/booking.test.ts(27,28): error TS4104: The type 'readonly [readonly ["Dilshod aka", 4], readonly ["Malika", 2]]' is 'readonly' and cannot be assigned to the mutable type '[string, number][]'.«Parametrda readonly — va'da» bo'limidagi qoidaning haqiqiy misoli. npx tsc --pretty false — chiqishsiz (chiqish kodi 0). Testlarni faqat shu fayl uchun ishga tushiramiz: node --test 04-massiv-tuple/booking.test.ts. (Papka nomini berish ishlamaydi: node --test 04-massiv-tuple/ uni fayl deb qidiradi va Cannot find module beradi.) Bizda (Node 24.21.0) shunday chiqdi:
✔ parseTime: matndan tuple (1.2691ms)
✔ parseTime: buzuq matn — RangeError (0.4075ms)
✔ isBookable: 10:00–22:00 chegaralari (0.1576ms)
✔ totalPeople: bronlardagi odamlar (0.1407ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 110.4381XATOLAR.md ga bu darsning yangi xabarlarini qo'shing: TS2542, TS4104, TS2493, TS2362, TS7034, TS18048, TS2314. Keyin kurs/mashqlar papkasidan:
git add 15/04-massiv-tuple 15/XATOLAR.md
git commit -m "15/04: booking.ts — tuple va readonly turlar, testlar"10. Real ishda
- React'dagi
useState(React — interfeys yasash kutubxonasi, 17-qismdan o'rganamiz) tuple qaytaradi:const [count, setCount] = useState(0). Ikkita o'rin — qiymat va uni o'zgartiruvchi funksiya. Siz endi bu yozuv nima ekanini bilasiz. Object.entriesnatijasi — tuple'lar massivi.Object.entries({ osh: 35000, manti: 30000 })ning turi —[string, number][]: har juftlik —[kalit, qiymat].- Koordinatalar, oraliqlar, juftliklar:
[lat, lng],[boshi, oxiri](vazifalardagiOraliq),[soat, daqiqa]— tuple'ning tabiiy joyi. readonlyparametrlar — kutubxonalar va katta loyihalarda odatiy uslub: funksiya imzosidan uning massivni buzmasligi ko'rinib turadi.- Intervyu: "Array va tuple farqi?", "
readonlyvaObject.freezefarqi?", "as constnima qiladi?" — tez-tez so'raladi.
Xulosa
- Massiv turi —
number[]yokiArray<number>, bir xil.|li element turi — qavsda:(string | number)[]. Bo'sh massivga tur yozing. readonly number[]—push,sort, indeksga yozish yo'q. Massivni faqat o'qiydigan parametrda ishlating. Bu faqat tur — ishlash paytida himoyaObject.freezeda.- Tuple — aniq o'rinlar:
[string, number]. Nomlangan ([open: number, close: number]), ixtiyoriy (note?: string) va rest (...number[]) elementlar bo'ladi. TypeScript tuple'ni o'zi chiqarmaydi — natija turini yozing. as const— literal turlar + tuple +readonly. O'zgarmas ro'yxatlar uchun.- Oddiy massivda
arr[i]turiundefinedni hisobga olmaydi.noUncheckedIndexedAccessbuni tuzatadi.
Keyingi dars: Obyekt turlari — obyektning shaklini ixtiyoriy va readonly xususiyatlar bilan yozamiz va TypeScript ortiqcha xususiyatlarni qanday ushlashini ko'ramiz.
Manbalar
- TypeScript Handbook: "Everyday Types" (Arrays) — typescriptlang.org/docs/handbook/2/everyday-types.html#arrays
- TypeScript Handbook: "Object Types" (The ReadonlyArray Type, Tuple Types, readonly Tuple Types) — typescriptlang.org/docs/handbook/2/objects.html#tuple-types
- TypeScript Release Notes 3.4 (
as const,readonlymassivlar) va 4.0 (nomlangan tuple elementlari) — typescriptlang.org/docs/handbook/release-notes/ - TSConfig:
noUncheckedIndexedAccess— typescriptlang.org/tsconfig#noUncheckedIndexedAccess
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!