Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. Obyekt turini yozish
- 2.1 Jingalak qavsda: nom va tur
- 2.2 Asosiy joyi — funksiya parametri
- 2.3 Yetishmaydigan xususiyat
- 2.4 Ichma-ich obyektlar va obyektlar massivi
- 2.5 Obyekt ichidagi funksiya
- 3. Ixtiyoriy xususiyat: ?
- 3.1 "Bo'lmasligi ham mumkin"
- 3.2 Tekshirmasdan ishlatsangiz
- 3.3 note?: string va note: string | undefined — bir xilmi?
- 3.4 exactOptionalPropertyTypes — qat'iyroq ?
- 4. readonly xususiyat
- 4.1 Faqat o'qish uchun
- 4.2 readonly — sayoz (shallow)
- 4.3 readonly faqat tekshiruvda
- 5. Ortiqcha xususiyat tekshiruvi
- 5.1 Turda yo'q xususiyat
- 5.2 Freshness: tekshiruv faqat "yangi" obyektda
- 5.3 Tekshiruv qayerlarda ishlaydi
- 5.4 Tekshiruvni "aylanib o'tish" — yomon fikr
- 6. TypeScript nimani ushlamaydi
- 6.1 readonly ni "unutadigan" o'zgaruvchi
- 6.2 Tashqaridan kelgan obyekt
- 7. Ko'p uchraydigan xatolar
- 7.1 Tur o'rniga qiymat yozish
- 7.2 ? ni tekshirmasdan ishlatish
- 7.3 readonly ni chuqur deb o'ylash
- 7.4 Ortiqcha xususiyat xatosini o'zgaruvchi bilan "yashirish"
- 8. Mashqlar
- 1-mashq (oson): Qaysi biri o'tadi?
- 2-mashq (o'rta): Turini yozing
- 3-mashq (qiyin): Amaliy tajriba — «Bahor» cheki
- 9. Real ishda
- Xulosa
- Manbalar
TypeScript obyekt turlari: ixtiyoriy, readonly va ortiqcha xususiyatlar
Qisqacha: Obyekt turi — obyektning shakli: qaysi xususiyatlar bor va har birining turi qanday. U jingalak qavsda yoziladi:
{ dish: string; price: number }. Xususiyat nomidan keyingi?— "bo'lmasligi ham mumkin" (ixtiyoriy), oldidagireadonly— "faqat o'qish uchun". TypeScript yangi yozilgan obyekt literalida turda yo'q xususiyatni ham ushlaydi — bu ortiqcha xususiyat tekshiruvi (excess property check).
Bu darsda
- Obyekt turini yozasiz va uni funksiya parametrida ishlatasiz.
- Ixtiyoriy xususiyat (
?) bilan ishlashni va undagiundefinedtuzog'ini bilasiz. readonlyxususiyat nimani taqiqlashini va nimani taqiqlamasligini tushuntira olasiz.- Ortiqcha xususiyat tekshiruvi qachon ishlashini va freshness ("yangi obyekt") qoidasini bilasiz.
- TypeScript obyektlarda nimani ushlamasligini ko'rasiz.
Oldin bilishingiz kerak: Massiv va tuple turlari, Obyekt: kalit-qiymat juftliklari, ??, ?. va mantiqiy tayinlash.
1. Nega bu kerak?
O'tgan darsda massiv va tuple turlarini yozdik va ko'rdik: o'rinlar ko'payib ketsa, [3] nima ekanini hech kim eslay olmaydi. Unda nomli maydonlari bor obyekt yaxshiroq. Bugun obyektning turini yozishni o'rganamiz.
Sardor «Bahor» kassasi uchun chek qatorini chiqaradigan funksiya yozdi:
function printLine(line) {
console.log(line.dish, line.price * line.qty);
}
printLine({ dish: "Osh", price: 35000, quantity: 2 });Konsolda:
Osh NaNFunksiya line.qty ni o'qiydi, buyurtma esa quantity deb yozilgan. line.qty — undefined, 35000 * undefined esa NaN. Xato xabari yo'q, chekda — "Osh NaN".
Ikkinchi voqea. Jasur aka menyuga izoh maydonini qo'shishni so'radi: "achchiqsiz", "piyozsiz". Izoh hamma buyurtmada bo'lmaydi. Sardor izohni katta harf bilan chiqaradigan joy yozdi va birinchi izohsiz buyurtmada sahifa TypeError bilan yiqildi.
Ikkala xato ham bitta savolga borib taqaladi: bu obyektda qaysi xususiyatlar bor va qaysilari bo'lmasligi mumkin? JavaScript bu savolga javob bermaydi. Obyekt turi esa javobni kodning o'ziga yozadi.
2. Obyekt turini yozish
2.1 Jingalak qavsda: nom va tur
Obyekt turi (object type) — obyektning shakli: unda qaysi xususiyatlar bor va har biri qaysi turda. Kundalik o'xshatish — bankdagi ariza blankasi: "Ism — harflar bilan", "Summa — raqam bilan". Blankaga qarab nima yozish kerakligini bilasiz.
const item: { dish: string; price: number } = {
dish: "Osh",
price: 35000,
};
console.log(`${item.dish}: ${item.price} so'm`); // Osh: 35000 so'mYozuv obyektning o'ziga o'xshaydi, lekin qiymatlar o'rnida turlar turadi: dish: string, price: number. Xususiyatlar orasida nuqtali vergul ; qo'yiladi. Vergul , ham ishlaydi, lekin ko'pchilik jamoalar nuqtali vergulni tanlaydi — biz ham shunday yozamiz.
Tur chiqarish darsida ko'rgan edik: const order = { dish: "Osh", price: 35000 } ga sichqonchani olib borsangiz, muharrir { dish: string; price: number; } ni ko'rsatadi. Bu — o'sha obyekt turi, faqat TypeScript uni o'zi chiqargan. Endi uni o'zimiz yozyapmiz.
2.2 Asosiy joyi — funksiya parametri
O'zgaruvchiga obyekt turini kamdan-kam yozamiz — qiymatdan chiqariladi. Asosiy joyi — funksiya parametri: u yerda TypeScript turni chiqara olmaydi («Funksiya parametrlari — doim» qoidasi). Sardorning funksiyasini ko'chiramiz:
function printLine(line: {
dish: string;
price: number;
quantity: number;
}) {
console.log(line.dish, line.price * line.qty);
}Kompilyator:
TS2339: Property 'qty' does not exist on type '{ dish: string; price: number; quantity: number; }'.Tarjimasi: "{ dish: string; price: number; quantity: number; } turida qty xususiyati yo'q". Endi xato funksiyaning ichida, chaqiruvni kutmasdan topildi. Xabardagi uzun tur — parametrning to'liq shakli: TypeScript qaysi xususiyatlar borligini ro'yxat qilib berdi, ular orasida qty yo'q.
Tuzatilgan va to'g'ri chaqirilgan variant:
function printLine(line: {
dish: string;
price: number;
quantity: number;
}) {
console.log(line.dish, line.price * line.quantity);
}
printLine({ dish: "Osh", price: 35000, quantity: 2 });Konsolda:
Osh 700002.3 Yetishmaydigan xususiyat
Shartnoma ikki tomonlama. Funksiya ichida mavjud xususiyatni o'qish kerak, chaqiruvchi esa hamma kerakli xususiyatni berishi kerak:
function printLine(line: {
dish: string;
price: number;
quantity: number;
}) {
console.log(line.dish, line.price * line.quantity);
}
printLine({ dish: "Osh", price: 35000 });Kompilyator:
TS2741: Property 'quantity' is missing in type '{ dish: string; price: number; }' but required in type '{ dish: string; price: number; quantity: number; }'.Tarjimasi: "quantity xususiyati { dish: string; price: number; } turida yo'q, lekin { dish; price; quantity } turida majburiy". Birinchi tur — siz bergan obyekt, ikkinchisi — kutilgan shakl. Bu xabarni ko'p ko'rasiz: "is missing … but required" — "yetishmaydi, lekin majburiy".
Maslahat: Uzun xabarlarda ikki turni ko'z bilan solishtirish qiyin. Xabardagi birinchi so'zga qarang:
Property 'quantity'— aynan qaysi xususiyat yetishmayotgani shu yerda yozilgan.
2.4 Ichma-ich obyektlar va obyektlar massivi
Obyekt turi ichida boshqa obyekt turi yoki massiv bo'lishi mumkin. Buyurtma: mehmon ismi va taomlar ro'yxati.
function orderTotal(order: {
guest: string;
items: { dish: string; price: number }[];
}) {
let sum = 0;
for (const item of order.items) {
sum += item.price;
}
return sum;
}
const total = orderTotal({
guest: "Dilshod aka",
items: [
{ dish: "Osh", price: 35000 },
{ dish: "Ko'k choy", price: 5000 },
],
});
console.log(total); // 40000items: { dish: string; price: number }[] — "obyektlar massivi": o'tgan darsdagi T[] yozuvi, faqat T o'rnida obyekt turi. Sikldagi item ning turini TypeScript o'zi chiqardi: { dish: string; price: number; }.
Ko'rib turibsiz: obyekt turi uzunlashib ketdi va orderTotal ni chaqiradigan har joyda uni qayta yozish kerak bo'lardi. Turga nom berish bu muammoni hal qiladi — keyingi darsda.
2.5 Obyekt ichidagi funksiya
Xususiyat funksiya ham bo'lishi mumkin. Turda u qavslar va natija turi bilan yoziladi:
const kitchen: { name: string; isOpen(hour: number): boolean } = {
name: "Bahor",
isOpen(hour) {
return hour >= 7 && hour < 23;
},
};
console.log(kitchen.isOpen(6), kitchen.isOpen(12)); // false trueisOpen(hour: number): boolean — "isOpen metodi: son oladi, mantiqiy qiymat qaytaradi". Obyektda hour ga tur yozmadik — u turdan chiqarildi (kontekst). Funksiya turlarining hamma ko'rinishlarini Funksiyalarni tiplash darsida o'rganamiz.
Tekshirib ko'ring:
function greet(guest: { name: string; vip: boolean }) {…}nigreet({ name: "Malika" })deb chaqirsa nima bo'ladi?
Javob
Xato: TS2741: Property 'vip' is missing in type '{ name: string; }' but required in type '{ name: string; vip: boolean; }'. Turda vip majburiy — ? belgisi yo'q. JavaScript'da funksiya ichida guest.vip jim undefined bo'lardi va if (guest.vip) "VIP emas" deb hisoblardi. Balki to'g'ri, balki yo'q — TypeScript sizdan aniq javob so'rayapti.
3. Ixtiyoriy xususiyat: ?
3.1 "Bo'lmasligi ham mumkin"
Izoh hamma buyurtmada bo'lmaydi. Buni turga yozish uchun xususiyat nomidan keyin ? qo'yiladi:
function noteText(order: { dish: string; note?: string }) {
return order.note ?? "izohsiz";
}
console.log(noteText({ dish: "Osh" })); // izohsiz
const withNote = { dish: "Manti", note: "piyozsiz" };
console.log(noteText(withNote)); // piyozsizIxtiyoriy xususiyat (optional property) — obyektda bo'lishi ham, bo'lmasligi ham mumkin bo'lgan xususiyat. Ikkala chaqiruv ham to'g'ri: biri izohsiz, biri izoh bilan.
Funksiya ichida order.note ning turi — string | undefined ("satr yoki undefined"). Hover ham shuni ko'rsatadi. Shuning uchun biz ?? bilan standart matn berdik.
3.2 Tekshirmasdan ishlatsangiz
«Nega bu kerak?» bo'limidagi ikkinchi voqea — izohni katta harf bilan chiqarish:
function shoutNote(order: { dish: string; note?: string }) {
return order.note.toUpperCase();
}Kompilyator:
TS18048: 'order.note' is possibly 'undefined'.Tarjimasi: "order.note undefined bo'lishi mumkin". Bu xabarni o'tgan darsda noUncheckedIndexedAccess bilan ko'rgan edik. Bu safar hech qanday bayroq kerak emas: ? ning o'zi "bo'lmasligi mumkin" deydi, strict esa buni hisobga olishga majbur qiladi.
Uch xil tuzatish bor, qaysi birini tanlash ma'noga bog'liq:
function shoutNote(order: { dish: string; note?: string }) {
// 1) ?. — izoh bo'lmasa, natija undefined
const a = order.note?.toUpperCase();
// 2) ?? — izoh bo'lmasa, standart matn
const b = (order.note ?? "izohsiz").toUpperCase();
// 3) if — izoh bo'lmasa, boshqa yo'l
if (order.note === undefined) {
return `${a} | ${b}`;
}
return order.note.toUpperCase();
}
console.log(shoutNote({ dish: "Osh" })); // undefined | IZOHSIZ
const manti = { dish: "Manti", note: "piyozsiz" };
console.log(shoutNote(manti)); // PIYOZSIZUchinchi yo'l qiziq: if dan keyin TypeScript order.note ni endi string deb biladi. Bu toraytirish (narrowing) — JSDoc darsida ko'rgansiz, to'liq — Narrowing: turni toraytirish darsida.
3.3 note?: string va note: string | undefined — bir xilmi?
Deyarli, lekin bitta farq bor. Ikkinchisida kalit majburiy, faqat qiymati undefined bo'lishi mumkin:
const order: { dish: string; note: string | undefined } = {
dish: "Osh",
};Kompilyator:
TS2741: Property 'note' is missing in type '{ dish: string; }' but required in type '{ dish: string; note: string | undefined; }'.| Turdagi yozuv | { dish: "Osh" } |
{ dish: "Osh", note: undefined } |
|---|---|---|
note?: string |
(standart sozlamada) | |
note: string | undefined |
TS2741 |
Qachon qaysi? Odatda ? — "bu ma'lumot bo'lmasligi mumkin". : string | undefined esa chaqiruvchini "bu haqida o'ylab ko'rdim" deb aniq yozishga majbur qiladi — masalan, "izohni bo'shatish" degan buyruqda.
3.4 exactOptionalPropertyTypes — qat'iyroq ?
Jadvaldagi "standart sozlamada" so'ziga e'tibor bering. Bir bayroq bu qoidani qat'iylashtiradi:
// @ts-options: {"exactOptionalPropertyTypes": true}
const order: { dish: string; note?: string } = {
dish: "Osh",
note: undefined,
};Kompilyator:
TS2375: Type '{ dish: string; note: undefined; }' is not assignable to type '{ dish: string; note?: string; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Types of property 'note' are incompatible.
Type 'undefined' is not assignable to type 'string'.exactOptionalPropertyTypes ("aniq ixtiyoriy xususiyat turlari") yoqilsa, note?: string faqat ikki holatni bildiradi: kalit yo'q yoki kalitda satr. note: undefined deb yozish — uchinchi holat, endi xato. Xabar tuzatishni ham aytyapti: "maqsad turiga undefined qo'shing" — note?: string | undefined.
Nega bu muhim? Ba'zi kodlar "kalit bormi" ni tekshiradi ("note" in order, Object.keys). { note: undefined } da kalit bor, {} da — yo'q. Bayroq shu farqni yo'qotmaydi. U strict ga kirmaydi, lekin TypeScript 7 ning tsc --init i uni yoqib qo'yadi (TypeScript'ni o'rnatish darsidagi fayl). To'liq — Strict bayroqlar oilasi darsida.
Tekshirib ko'ring:
function fee(order: { km?: number }) { return order.km * 2000; }—tscnima deydi va qanday tuzatasiz, agar masofa yo'q bo'lsa yetkazish bepul bo'lsa?
Javob
TS18048: 'order.km' is possibly 'undefined'. — km ixtiyoriy. Ma'nosiga mos tuzatish: return (order.km ?? 0) * 2000; — masofa yo'q bo'lsa 0 km, demak 0 so'm. ?. bu yerda yordam bermaydi: undefined * 2000 baribir NaN.
4. readonly xususiyat
4.1 Faqat o'qish uchun
Buyurtmaning raqami (id) bir marta beriladi va hech qachon o'zgarmasligi kerak. Massivlardagi kabi, readonly so'zi bu yerda ham ishlaydi — xususiyat oldiga yoziladi:
const order: { readonly id: number; status: string } = {
id: 101,
status: "yangi",
};
order.status = "tayyor";
order.id = 102;Kompilyator:
TS2540: Cannot assign to 'id' because it is a read-only property.Tarjimasi: "id ga qiymat berib bo'lmaydi, chunki u faqat o'qish uchun xususiyat". status ni o'zgartirish ruxsat — u readonly emas. Bitta obyektda o'zgaradigan va o'zgarmaydigan xususiyatlar yonma-yon tura oladi.
4.2 readonly — sayoz (shallow)
readonly faqat o'sha xususiyatni himoya qiladi. Ichidagi obyektni emas:
const order: {
readonly guest: { name: string };
readonly items: string[];
} = {
guest: { name: "Malika" },
items: ["Osh"],
};
order.guest.name = "Bobur";
order.items.push("Manti");
console.log(order.guest.name); // Bobur
console.log(order.items); // [ 'Osh', 'Manti' ]tsc — xatosiz. order.guest = … (boshqa obyekt berish) taqiqlangan, lekin order.guest.name = … — ichki obyektning xususiyati, u readonly emas. Xuddi shunday, items ning o'zi o'zgarmaydi, lekin massiv ichiga push qilish mumkin.
Ichkarisini ham himoyalash uchun har darajaga readonly yoziladi:
const order: {
readonly guest: { readonly name: string };
readonly items: readonly string[];
} = {
guest: { name: "Malika" },
items: ["Osh"],
};
order.guest.name = "Bobur";
order.items.push("Manti");Kompilyator:
TS2540: Cannot assign to 'name' because it is a read-only property.
TS2339: Property 'push' does not exist on type 'readonly string[]'.Birinchi xabar: «name ga qiymat yozib bo'lmaydi, chunki u faqat o'qiladigan (read-only) xususiyat». Endi ichki obyekt ham himoyalangan.
Ikkinchi xabar — o'tgan darsdan tanish readonly string[]. Hamma xususiyatni birdan readonly qiladigan Readonly<…> yozuvi ham bor — uni Utility types darsida ko'ramiz.
4.3 readonly faqat tekshiruvda
Massivdagi kabi, readonly va ? ham — faqat tur. Mana menu.ts:
const dish: { readonly name: string; note?: string } = {
name: "Osh",
};
console.log(dish); // { name: 'Osh' }tsc 7.0.2 uni shunday yozadi:
const dish = {
name: "Osh",
};
console.log(dish);
export {};Turdan hech narsa qolmadi. Ishlash paytida himoya kerak bo'lsa — Object.freeze. Qolgan hollarda readonly yetadi: tekshiruvdan o'tgan kod uni buzmaydi.
Tekshirib ko'ring:
const table: { readonly seats: number[] } = { seats: [4, 4, 6] };—table.seats[0] = 2xato beradimi?table.seats = [2]chi?
Javob
table.seats[0] = 2 — xato yo'q: readonly faqat seats xususiyatining o'zini himoyalaydi, massiv esa oddiy number[]. table.seats = [2] — TS2540: xususiyatga yangi massiv berish taqiqlangan. Ikkalasini ham taqiqlash uchun: readonly seats: readonly number[].
5. Ortiqcha xususiyat tekshiruvi
5.1 Turda yo'q xususiyat
Endi teskari holat: obyektda turda yo'q xususiyat bor.
function printLine(line: {
dish: string;
price: number;
quantity: number;
}) {
console.log(line.dish, line.price * line.quantity);
}
printLine({ dish: "Osh", price: 35000, quantity: 2, spicy: true });Kompilyator:
TS2353: Object literal may only specify known properties, and 'spicy' does not exist in type '{ dish: string; price: number; quantity: number; }'.Tarjimasi: "Obyekt literali faqat ma'lum xususiyatlarni ko'rsatishi mumkin, spicy esa { dish; price; quantity } turida yo'q". Obyekt literali (object literal) — kodda jingalak qavs bilan shu yerning o'zida yozilgan obyekt: { dish: "Osh", … }. Bu ortiqcha xususiyat tekshiruvi (excess property check).
Nega bu xato? spicy funksiyaga hech qanday zarar qilmaydi-ku. Gap shundaki, ko'pincha ortiqcha xususiyat — imlo xatosi. Eng xavfli holat ixtiyoriy xususiyatda:
const order: { dish: string; note?: string } = {
dish: "Osh",
nte: "achchiqsiz",
};Kompilyator:
TS2561: Object literal may only specify known properties, but 'nte' does not exist in type '{ dish: string; note?: string | undefined; }'. Did you mean to write 'note'?note ixtiyoriy — u bo'lmasa ham xato yo'q. Agar TypeScript nte ga indamasa, obyekt "izohsiz buyurtma" bo'lib qolardi, Jasur aka esa "achchiqsiz" yozilgan oshni achchiq holda olardi. Tekshiruv buni ushladi va hatto to'g'ri nomni taklif qildi: "note deb yozmoqchimidingiz?"
5.2 Freshness: tekshiruv faqat "yangi" obyektda
Endi kutilmagan narsa. Xuddi o'sha obyektni avval o'zgaruvchiga olamiz:
function printLine(line: {
dish: string;
price: number;
quantity: number;
}) {
console.log(line.dish, line.price * line.quantity);
}
const fromKitchen = {
dish: "Osh",
price: 35000,
quantity: 2,
spicy: true,
};
printLine(fromKitchen);Konsolda:
Osh 70000tsc — xatosiz. Nega? Ortiqcha xususiyat tekshiruvi faqat yangi yozilgan obyekt literalida ishlaydi. TypeScript buni freshness ("yangilik") deydi: { … } aynan shu joyda yozilgan bo'lsa, u "yangi", va undagi ortiqcha xususiyatni tashlab yuboradigan boshqa hech kim yo'q — demak bu deyarli aniq xato.
fromKitchen esa o'zgaruvchi. U boshqa joyda ham ishlatilishi mumkin: oshxona ekranida spicy kerak, chekda — yo'q. Unda printLine uchun asosiy savol bitta: "menga kerakli uchta xususiyat bormi?" Bor — demak mos. Bu qoida strukturaviy tiplash deyiladi, uni Strukturaviy tiplash darsida to'liq ko'ramiz.
flowchart TD
A["Obyekt tur kutilgan joyga<br/>berilyapti"] --> B{"Kerakli xususiyatlar<br/>hammasi bormi?"}
B -- "yo'q" --> X["TS2741: is missing"]
B -- "ha" --> C{"Shu yerda yozilgan<br/>literalmi { … }?"}
C -- "ha (fresh)" --> D{"Turda yo'q<br/>xususiyat bormi?"}
D -- "ha" --> Y["TS2353 / TS2561"]
D -- "yo'q" --> OK["Mos ✅"]
C -- "yo'q, o'zgaruvchi" --> OKSxemani yuqoridan o'qing: yetishmaydigan xususiyat har doim xato. Ortiqcha xususiyat esa faqat yangi literalda xato.
5.3 Tekshiruv qayerlarda ishlaydi
Yangi literal uch joyda tekshiriladi: o'zgaruvchiga berilganda (const x: T = { … }), argument sifatida (f({ … })) va return { … } da:
function makeLine(): { dish: string; price: number } {
return { dish: "Manti", price: 30000, qty: 1 };
}Kompilyator:
TS2353: Object literal may only specify known properties, and 'qty' does not exist in type '{ dish: string; price: number; }'.5.4 Tekshiruvni "aylanib o'tish" — yomon fikr
Internetda ba'zan shunday maslahat uchraydi: "xato chiqsa, obyektni avval o'zgaruvchiga oling". Ishlaydi — lekin bu imlo xatosini yashirish. Ortiqcha xususiyat haqiqatan kerak bo'lsa, uni turga qo'shing (spicy?: boolean). Kalitlari oldindan noma'lum obyektlar uchun alohida yozuv bor — Index signature va Record darsida.
Tekshirib ko'ring:
const a = { dish: "Osh", price: 35000, size: "katta" }; const b: { dish: string; price: number } = a;— xato bormi?b.sizeni o'qish-chi?
Javob
Ikkinchi qatorda xato yo'q: a — o'zgaruvchi, yangi literal emas, kerakli dish va price bor. Lekin b.size — TS2339: Property 'size' does not exist on type '{ dish: string; price: number; }'. Qiymatda size bor, ammo b ning turi uni bilmaydi. TypeScript turga qaraydi, qiymatga emas.
6. TypeScript nimani ushlamaydi
6.1 readonly ni "unutadigan" o'zgaruvchi
Bu — TypeScript'ning ma'lum bo'shlig'i. readonly xususiyatli obyektni readonly siz turga berish mumkin:
const menuItem: { readonly name: string; readonly price: number } = {
name: "Osh",
price: 35000,
};
const editable: { name: string; price: number } = menuItem;
editable.price = 1;
console.log(menuItem.price); // 1tsc hech narsa demadi, oshning narxi esa 1 so'm bo'lib qoldi. editable va menuItem — bitta obyektga ikki havola (Havola semantikasi), editable orqali esa yozish ruxsat. Massivlarda bunday emas edi — readonly string[] ni string[] ga berish TS4104 xatosini berardi. Obyekt xususiyatlarida esa TypeScript readonly ni moslik tekshiruvida hisobga olmaydi.
Bundan xulosa: readonly — jamoa ichidagi kelishuv uchun yaxshi vosita, lekin u ishlash paytidagi qulf emas. Haqiqiy qulf — Object.freeze.
6.2 Tashqaridan kelgan obyekt
Tur chiqarish darsida ko'rganimizdek, JSON.parse — any qaytaradi. Obyekt turini yozish uni tekshirmaydi:
const saved = '{"dish":"Osh"}'; // eski versiya: narx saqlanmagan
const item: { dish: string; price: number } = JSON.parse(saved);
console.log(item.price.toFixed(0));tsc — xatosiz. Node esa:
TypeError: Cannot read properties of undefined (reading 'toFixed')Tur aytadi: price — son. Haqiqatda esa u umuman yo'q. Server javobi, localStorage, fayl — hammasini ishlash paytida tekshirish kerak. Buning yo'llarini Custom type guard va API ma'lumotlarini tiplash darslarida o'rganamiz.
7. Ko'p uchraydigan xatolar
7.1 Tur o'rniga qiymat yozish
Turni qiymat joyiga — = dan keyin — yozib qo'yish:
function printDish(item = { dish: string }) {
console.log(item);
}Kompilyator:
TS2693: 'string' only refers to a type, but is being used as a value here.Tarjimasi: "string faqat turni bildiradi, bu yerda esa qiymat sifatida ishlatilyapti". = dan keyin standart qiymat keladi, tur esa : dan keyin. Tuzatish: function printDish(item: { dish: string }). Ikkalasi kerak bo'lsa: item: { dish: string } = { dish: "Osh" }.
7.2 ? ni tekshirmasdan ishlatish
order.note.trim() — TS18048. Tuzatish: ?., ?? yoki if (order.note !== undefined) — «Tekshirmasdan ishlatsangiz» bo'limidagi uch yo'l.
7.3 readonly ni chuqur deb o'ylash
readonly guest: { name: string } — guest.name ni o'zgartirish mumkin. Tuzatish: har darajaga readonly yozing, massivga — readonly T[].
7.4 Ortiqcha xususiyat xatosini o'zgaruvchi bilan "yashirish"
Xato yo'qoladi, imlo xatosi qoladi. Tuzatish: nomini to'g'rilang yoki xususiyatni turga qo'shing.
8. Mashqlar
1-mashq (oson): Qaysi biri o'tadi?
function seat(guest: { name: string; vip?: boolean }) {
return guest.vip ? `${guest.name} — VIP zal` : guest.name;
}
const guest = { name: "Dilshod aka", vip: true };
console.log(seat(guest)); // Dilshod aka — VIP zal
console.log(seat({ name: "Bobur" })); // Boburseat({ name: "Malika", vip: "ha" }) — tsc xato beradimi (ha/yo'q): [:ha]. seat({ name: "Ali", vp: true }) xatosining kodi: TS[:2561]. Funksiya ichida guest.vip ning turi boolean | .
Yechim
vip: "ha"—TS2322: Type 'string' is not assignable to type 'boolean'.Ixtiyoriy bo'lsa ham, berilgan qiymat to'g'ri turda bo'lishi kerak.vp: true—TS2561("Did you mean to write 'vip'?"): yangi literal, ortiqcha xususiyat va o'xshash nom bor.guest.vip—boolean | undefined:?turgaundefinedni qo'shadi. Shartda (guest.vip ? … : …)undefined"yolg'on" hisoblanadi, shuning uchun bu yerda tekshiruv shart emas.
2-mashq (o'rta): Turini yozing
Bu JavaScript funksiya bron xabarini tuzadi. .ts ga ko'chiring: parametrga obyekt turi yozing. Bron vaqti va mehmon ismi majburiy, odamlar soni ixtiyoriy (bo'lmasa — 2), izoh ixtiyoriy. Bron id si o'zgarmasligi kerak.
function bookingText(booking) {
const people = booking.people ?? 2;
const note = booking.note ? ` (${booking.note})` : "";
return `#${booking.id} ${booking.time} — ${booking.guest}, ` +
`${people} kishi${note}`;
}
console.log(bookingText({ id: 7, time: "19:30", guest: "Malika" }));Konsolda:
#7 19:30 — Malika, 2 kishiIshora: ?? — Nullish coalescing darsidan; ixtiyoriy xususiyat — nom?: tur.
Yechim
function bookingText(booking: {
readonly id: number;
time: string;
guest: string;
people?: number;
note?: string;
}): string {
const people = booking.people ?? 2;
const note = booking.note ? ` (${booking.note})` : "";
return `#${booking.id} ${booking.time} — ${booking.guest}, ` +
`${people} kishi${note}`;
}
console.log(bookingText({ id: 7, time: "19:30", guest: "Malika" }));
console.log(
bookingText({ id: 8, time: "20:00", guest: "Bobur", people: 4,
note: "deraza yonida" }),
);Konsolda:
#7 19:30 — Malika, 2 kishi
#8 20:00 — Bobur, 4 kishi (deraza yonida)readonly id— bron raqami o'zgarmaydi. Funksiya uni faqat o'qiydi, shuning uchun bu shartnomaga hech narsa xalaqit bermaydi.people?vanote?— ixtiyoriy.booking.people ?? 2ning turinumber:??undefinedni olib tashladi.- Natija turi
: string— funksiya boshqa joyda ham ishlatilsa, shartnoma aniq bo'lsin.
3-mashq (qiyin): Amaliy tajriba — «Bahor» cheki
Mashq kurs/mashqlar/15/ papkasida, Tur annotatsiyasi darsida tayyorlangan umumiy tsconfig.json bilan bajariladi. 05-obyekt-turlari/receipt.ts faylini yarating. Birinchi variant — JavaScript'dan ko'chirilgan, turlari yozilgan, lekin ichi o'zgartirilmagan:
// 05-obyekt-turlari/receipt.ts — «Bahor» cheki
type Line = {
readonly dish: string;
readonly price: number;
readonly qty: number;
};
export function lineTotal(line: Line): number {
return line.price * line.qty;
}
export function addLine(
order: { readonly guest: string; readonly lines: readonly Line[] },
line: Line,
) {
order.lines.push(line);
return order;
}
export function receiptLines(order: {
readonly lines: readonly Line[];
readonly note?: string;
}): string[] {
const rows = order.lines.map(
(line) => `${line.dish} x${line.qty}: ${lineTotal(line)}`,
);
if (order.note.trim() !== "") {
rows.push(`Izoh: ${order.note}`);
}
return rows;
}type Line = { … } — chek qatori turiga nom berdik, toki u uch joyda takrorlanmasin (o'tgan darsdagi Booking kabi; batafsil — keyingi darsda).
npx tsc --pretty falseni ishga tushiring va xatolarni o'qing.addLineni tuzating: u asl buyurtmani o'zgartirmasin, yangi buyurtma qaytarsin (ishora: spread —{ ...order, lines: [...order.lines, line] }). Natija turini yozing.receiptLinesni tuzating: izoh bo'lmasa yoki faqat bo'sh joylardan iborat bo'lsa, "Izoh" qatori chiqmasin. Izohnitrimqilib chiqaring. Izohdan oldinJami: …qatorini qo'shing.05-obyekt-turlari/receipt.test.tsda testlar yozing: qator summasi;addLinedan keyin asl buyurtma o'zgarmagani; izohsiz chek; izohli va bo'sh izohli chek.
Yechim
1-qadamda tsc 7.0.2 shunday dedi:
05-obyekt-turlari/receipt.ts(16,15): error TS2339: Property 'push' does not exist on type 'readonly Line[]'.
05-obyekt-turlari/receipt.ts(27,7): error TS18048: 'order.note' is possibly 'undefined'.Ikkalasi ham bugungi mavzu. Birinchisi — readonly massiv: JavaScript'dagi addLine mehmonning asl buyurtmasini jim o'zgartirardi. Kassa ekranidagi "eski" buyurtma ham yangi taom bilan to'lib qolardi. Ikkinchisi — ixtiyoriy note: izohsiz buyurtmada undefined.trim() — TypeError.
// 05-obyekt-turlari/receipt.ts — «Bahor» cheki
type Line = {
readonly dish: string;
readonly price: number;
readonly qty: number;
};
export function lineTotal(line: Line): number {
return line.price * line.qty;
}
// Yangi buyurtma qaytaradi: asl obyekt va massiv o'zgarmaydi
export function addLine(
order: { readonly guest: string; readonly lines: readonly Line[] },
line: Line,
): { readonly guest: string; readonly lines: readonly Line[] } {
return { ...order, lines: [...order.lines, line] };
}
export function receiptLines(order: {
readonly lines: readonly Line[];
readonly note?: string;
}): string[] {
const rows = order.lines.map(
(line) => `${line.dish} x${line.qty}: ${lineTotal(line)}`,
);
let total = 0;
for (const line of order.lines) {
total += lineTotal(line);
}
rows.push(`Jami: ${total}`);
const note = order.note?.trim();
if (note) {
rows.push(`Izoh: ${note}`);
}
return rows;
}order.note?.trim() — izoh bo'lmasa undefined, bo'lsa — kesilgan satr. if (note) ikki holatni birdan o'tkazib yuboradi: undefined va bo'sh satr "" (ikkalasi ham "yolg'on"). addLine ning natija turi parametrnikining aynan nusxasi — uzun, takroriy. Aynan shu takror keyingi darsning sababi.
// 05-obyekt-turlari/receipt.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { lineTotal, addLine, receiptLines } from "./receipt.ts";
const osh = { dish: "Osh", price: 35000, qty: 2 };
const tea = { dish: "Ko'k choy", price: 5000, qty: 1 };
test("lineTotal: narx × soni", () => {
assert.equal(lineTotal(osh), 70000);
});
test("addLine: yangi buyurtma, asli o'zgarmaydi", () => {
const order = { guest: "Dilshod aka", lines: [osh] };
const next = addLine(order, tea);
assert.equal(next.lines.length, 2);
assert.equal(order.lines.length, 1);
assert.equal(next.guest, "Dilshod aka");
});
test("receiptLines: izohsiz", () => {
assert.deepEqual(receiptLines({ lines: [osh, tea] }), [
"Osh x2: 70000",
"Ko'k choy x1: 5000",
"Jami: 75000",
]);
});
test("receiptLines: izoh bor va bo'sh izoh", () => {
const rows = receiptLines({ lines: [osh], note: " achchiqsiz " });
assert.equal(rows.at(-1), "Izoh: achchiqsiz");
assert.equal(receiptLines({ lines: [], note: " " }).length, 1);
});Testdagi osh va tea ga tur yozmadik: ular Line ga mos shaklda, tsc buni chaqiruv joyida tekshiradi. order esa oddiy (o'zgaruvchan) massivli obyekt — uni readonly parametrga berish mumkin. npx tsc --pretty false — chiqishsiz (chiqish kodi 0). Keyin node --test 05-obyekt-turlari/receipt.test.ts — bizda (Node 24.21.0) shunday chiqdi, millisekundlar sizda boshqacha bo'ladi:
✔ lineTotal: narx × soni (0.9758ms)
✔ addLine: yangi buyurtma, asli o'zgarmaydi (0.2261ms)
✔ receiptLines: izohsiz (0.9993ms)
✔ receiptLines: izoh bor va bo'sh izoh (0.9422ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 156.7662XATOLAR.md ga bu darsning yangi xabarlarini qo'shing: TS2741, TS2353, TS2561, TS2540, TS2375, TS2693. Keyin kurs/mashqlar papkasidan:
git add 15/05-obyekt-turlari 15/XATOLAR.md
git commit -m "15/05: receipt.ts — obyekt turlari, readonly va ?"Oldinga qarab: Vazifalar qadami. vazifalar dagi VazifaMalumoti ham — obyekt turi: id, matn, bajarildi. Hozir u 12/39 dagi JSDoc @typedef da yozilgan. Keyingi darsda u ilovaning birinchi .ts fayliga — turlar.ts ga ko'chadi, uchala xususiyati readonly bo'ladi va unga nom beriladi. Shu yerda type yoki interface tanlovi haqiqiy xato bilan hal bo'ladi.
9. Real ishda
- Funksiya parametri sifatida obyekt — zamonaviy kodning odatiy uslubi:
createOrder({ guest, items, note }). Argumentlar tartibini eslash shart emas, ixtiyoriylari esa?bilan belgilanadi. React komponentlari (17-qismdan) ham ma'lumotni aynan shunday obyekt orqali oladi. - Ortiqcha xususiyat tekshiruvi — sozlama obyektlarida eng ko'p yordam beradi:
fetch(url, { methd: "POST" })kabi imlo xatosini kutubxona funksiyasini chaqirgan zahoti ko'rasiz. readonly— holat (state) obyektlarida: Redux, React holati kabi "o'zgartirmasdan, yangisini yasa" uslubidagi kodda keng tarqalgan.- Intervyu: "
?va| undefinedfarqi?", "Excess property check nima va nega o'zgaruvchi orqali o'tib ketadi?", "readonlyvaObject.freezefarqi?" — tez-tez so'raladi.
Xulosa
- Obyekt turi —
{ dish: string; price: number }. Asosiy joyi — funksiya parametri. Yetishmaydigan xususiyat —TS2741, mavjud bo'lmagani —TS2339. note?: string— ixtiyoriy, ichkaridastring | undefined. Ishlatishdan oldin?.,??yokiifbilan tekshiring (TS18048).readonly— qayta yozishni taqiqlaydi (TS2540), lekin sayoz va faqat tur: ishlash paytida himoya —Object.freeze.- Ortiqcha xususiyat faqat yangi literalda xato (
TS2353,TS2561). O'zgaruvchi orqali berilgan obyekt kerakli xususiyatlar bo'lsa yetadi. - Obyekt turi tashqaridan kelgan ma'lumotni tekshirmaydi:
JSON.parsenatijasi istalgan turga jim mos keladi.
Keyingi dars: type va interface — uzun obyekt turlariga nom beramiz, ikki yozuvning farqini ko'ramiz va vazifalar ning birinchi .ts faylini yaratamiz.
Manbalar
- TypeScript Handbook: "Object Types" (Optional Properties, readonly Properties) — typescriptlang.org/docs/handbook/2/objects.html
- TypeScript Handbook: "Object Types" → Excess Property Checks — typescriptlang.org/docs/handbook/2/objects.html#excess-property-checks
- TSConfig:
exactOptionalPropertyTypes— typescriptlang.org/tsconfig#exactOptionalPropertyTypes - TypeScript Release Notes 4.4 (
exactOptionalPropertyTypes) — typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!