Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tur annotatsiyasi
- 2.1 Yozilishi: nomdan keyin ikki nuqta
- 2.2 Annotatsiya xatoni ushlaydi
- 2.3 Qiymatsiz e'lon
- 3. Tur chiqarish (inference)
- 3.1 Birinchi qiymat turni belgilaydi
- 3.2 Muharrirda turni ko'rish
- 3.3 Funksiya natijasi ham chiqariladi
- 3.4 Kontekstdan chiqarish: callback parametrlari
- 4. let va const: literal tur va kengayish
- 4.1 Bir xil qiymat — ikki xil tur
- 4.2 Kengayish qachon seziladi?
- 4.3 Obyekt ichida — doim kengayadi
- 5. Annotatsiya qayerda shart?
- 5.1 Funksiya parametrlari — doim
- 5.2 Natija turi — boshqa fayllar ishlatadigan funksiyada
- 5.3 Qiymatsiz e'lon — doim
- 5.4 Qolgan hamma joyda — odatda yozmang
- 6. TypeScript nimani ushlamaydi
- 6.1 Annotatsiya — va'da, tekshiruv emas
- 6.2 Annotatsiya JavaScript'ga o'tmaydi
- 7. Ko'p uchraydigan xatolar
- 7.1 String katta harf bilan
- 7.2 Tur o'rniga qo'shtirnoqdagi so'z
- 7.3 Hamma joyga tur yozish
- 7.4 Natija turini yozmaslik va xatoni uzoqdan qidirish
- 8. Mashqlar
- 1-mashq (oson): Hover'ni oldindan ayting
- 2-mashq (o'rta): Ortiqchasini olib tashlang, kerakligini qo'shing
- 3-mashq (qiyin): Amaliy tajriba — «Bahor» hisobi
- 9. Real ishda
- Xulosa
- Manbalar
TypeScript tur annotatsiyasi va tur chiqarish (inference): turni qachon yozish kerak
Qisqacha: Tur annotatsiyasi — o'zgaruvchi yoki parametr nomidan keyin yoziladigan
: tur(let price: number = 35000). Lekin ko'p hollarda uni yozish shart emas: TypeScript turni boshlang'ich qiymatdan o'zi chiqaradi — bu tur chiqarish (inference). Annotatsiya kerak bo'lgan asosiy joylar — funksiya parametrlari, qiymatsiz e'lon qilingan o'zgaruvchilar va boshqa fayllar ishlatadigan funksiyalarning natija turi.
Bu darsda
: string,: number,: booleanannotatsiyalarini yozasiz va TS xabarlarini o'qiysiz.- TypeScript turni qiymatdan qanday chiqarishini va muharrirda buni qanday ko'rishni bilasiz.
letvaconstnega har xil tur olishini (literal tur va kengayish) tushuntira olasiz.- Tur qayerda shart, qayerda ortiqcha ekanini ajratasiz.
- Annotatsiya nimani qilmasligini bilasiz: u qiymatni o'zgartirmaydi va ishlash paytida tekshirmaydi.
Oldin bilishingiz kerak: TypeScript'ni o'rnatish va ishga tushirish, JSDoc va // @ts-check, let va const bilan o'zgaruvchilar.
1. Nega bu kerak?
O'tgan darsda TypeScript'ni o'rnatdik va birinchi .ts faylni tsc bilan tekshirdik. Endi asosiy savol: turlarni qayerga va qancha yozish kerak?
Sardor «Bahor» kassasining eski kodini ko'chiryapti. Mana JavaScript'dagi bir parcha — mehmon choychaqani formaga yozadi, kassa uni jami summaga qo'shadi:
let total = 0;
const tipInput = "5000"; // formadan keldi — matn!
total = total + tipInput;
console.log(total); // 05000Natija — 5000 emas, "05000" satri. Son va satr qo'shilganda JavaScript ularni yopishtirib qo'ydi (Yashirin coercion qoidalari darsidagi tuzoq). Xato xabari yo'q, chekda esa g'alati raqam.
Sardor o'yladi: "TypeScript'da har bir o'zgaruvchiga tur yozib chiqishim kerak ekan". Lekin avval shu kodni hech o'zgartirmasdan .ts faylga qo'yib ko'ramiz:
let total = 0;
const tipInput = "5000";
total = total + tipInput;Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.TypeScript aytyapti: «string turidagi qiymatni number turidagi o'zgaruvchiga yozib bo'lmaydi».
Bitta ham tur yozmadik, lekin TypeScript xatoni topdi. U total ning turini 0 qiymatidan o'zi bilib oldi: son. total + tipInput esa satr beradi. Satrni songa mo'ljallangan o'zgaruvchiga yozib bo'lmaydi.
Bu darsning asosiy g'oyasi shu: TypeScript turlarning ko'pini o'zi chiqaradi. Sizning vazifangiz — u chiqara olmaydigan joylarni bilish va faqat o'sha yerga tur yozish.
2. Tur annotatsiyasi
2.1 Yozilishi: nomdan keyin ikki nuqta
Tur annotatsiyasi (type annotation) — o'zgaruvchi nomidan keyin ikki nuqta va tur: price: number. U TypeScript'ga "bu nom ostida faqat shu turdagi qiymat turadi" deb aytadi. Xuddi bozordagi qopga yopishtirilgan yorliq kabi: "faqat guruch". Qopga kartoshka solmoqchi bo'lsangiz, sotuvchi darhol to'xtatadi.
const dishName: string = "Osh";
let price: number = 35000;
let isOpen: boolean = true;
console.log(dishName, price, isOpen); // Osh 35000 trueUchta asosiy tur — sizga typeof darsidan tanish:
| Tur | Qanday qiymatlar | Misol |
|---|---|---|
string |
har qanday matn | "Osh", 'manti', `${n} so'm` |
number |
butun va kasr sonlar, NaN ham |
35000, 0.1, -5 |
boolean |
faqat ikki qiymat | true, false |
Tur nomlari kichik harf bilan yoziladi: string, String emas. Bu farq muhim — «Ko'p uchraydigan xatolar» bo'limida ko'ramiz.
JSDoc darsida xuddi shu narsani izohda yozgan edingiz. Taqqoslang:
/** @type {number} */
let price = 35000;TypeScript'da tur kodning o'zida, nom yonida turadi: let price: number = 35000;. G'oya va tekshiruvchi bir xil, yozuv qisqaroq.
2.2 Annotatsiya xatoni ushlaydi
Endi yorliqqa mos kelmagan qiymat beramiz. Narx forma maydonidan bo'sh joyi bilan ko'chirilgan:
let price: number = "35 000";Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.Tarjimasi: "string turini number turiga berib (yozib) bo'lmaydi". "Assignable" so'zi "qiymat sifatida berish mumkin" degani. Bu xabarni 15-qismda eng ko'p ko'rasiz. Uni har doim shunday o'qing: chapdagi tur — sizda bor qiymat, o'ngdagi tur — kutilgan tur.
tsc xato joyini o'zgaruvchi nomiga (price) ko'rsatadi, qiymatga emas. Sababi: shartnoma nom yonida yozilgan va buzilgan ham o'sha shartnoma.
2.3 Qiymatsiz e'lon
Ba'zan o'zgaruvchining qiymati keyinroq, shartga qarab aniqlanadi. Unda annotatsiya — TypeScript'ga turni aytishning yagona yo'li:
let guestName: string;
const hour = 19;
if (hour < 12) {
guestName = "Malika";
} else {
guestName = "Dilshod aka";
}
console.log(guestName); // Dilshod akaTypeScript ikkala tarmoqni ham kuzatadi: if da ham, else da ham qiymat berilgan. Demak, console.log ga yetganda guestName albatta satr. Bitta tarmoqni unutsangiz yoki qiymat berishdan oldin o'qisangiz:
let guestName: string;
console.log(guestName);Kompilyator:
TS2454: Variable 'guestName' is used before being assigned.Tarjimasi: "guestName o'zgaruvchisi qiymat berilishidan oldin ishlatilgan". JavaScript'da bu kod jim undefined chiqarardi. TypeScript esa uni xato deydi: siz "bu yerda satr bo'ladi" deb va'da bergansiz, lekin hali hech narsa yozmagansiz.
Tekshirib ko'ring:
let rating: number = 4.5;— xato bormi?let rating: number = "4.5";chi?
Javob
Birinchisida xato yo'q: number butun va kasr sonlarning hammasini o'z ichiga oladi. Ikkinchisida TS2322: Type 'string' is not assignable to type 'number'. — qo'shtirnoq ichidagi "4.5" son emas, satr. Qiymat ko'rinishi son kabi bo'lsa ham, turi satr.
3. Tur chiqarish (inference)
3.1 Birinchi qiymat turni belgilaydi
Annotatsiyasiz yozamiz:
let price = 35000;
price = 37000;
console.log(price); // 37000TypeScript 35000 ni ko'rib, price ning turini number deb belgiladi. Bu tur chiqarish (type inference) deyiladi: tur yozilmagan, lekin qiymatdan xulosa qilingan. Kundalik hayotdagi kabi: do'kondor qopga qarab "bu guruch qopi" deydi, yorliq shart emas.
Keyin boshqa son yozish mumkin — tur o'sha-o'sha. Satr yozsak-chi?
let price = 35000;
price = "arzon";Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.Xabar «Annotatsiya xatoni ushlaydi» bo'limidagi bilan aynan bir xil. Ya'ni TypeScript uchun let price = 35000 va let price: number = 35000 — bir xil shartnoma. Farqi faqat yozuvda.
Bu JavaScript'dan katta farq. JavaScript'da bitta let o'zgaruvchisiga avval son, keyin satr, keyin massiv yozish mumkin edi. TypeScript'da o'zgaruvchining turi e'lon qilingan paytda bir marta belgilanadi va o'zgarmaydi.
3.2 Muharrirda turni ko'rish
TypeScript qaysi turni chiqarganini qanday bilasiz? Eng qulay yo'l — sichqonchani nom ustiga olib borish (hover). VS Code kichik oynada turni ko'rsatadi:
Xuddi shu narsa TS Playground'da ham ishlaydi — sichqonchani so'z ustiga olib boring. Saytimizdagi har TypeScript kod bloki ostida «TS Playground'da ochish» havolasi bor: u kodni o'sha yerda ochadi. Telefonda o'qiyotgan bo'lsangiz, pastdagi jadvallarga qarang — ularda muharrir ko'rsatadigan turlar yozilgan. Saytning o'zida tur tekshiruvi yo'q: «Ishga tushir» turlarni olib tashlab, kodni oddiy JavaScript kabi bajaradi. Xatolarni ko'rish uchun Playground'ni oching.
Muharrir quyidagi kodlar uchun nima ko'rsatadi? Jadvaldagi o'ng ustun — haqiqiy natija (tsc 7.0.2 tekshirgan):
| Kod | Hover'da |
|---|---|
let price = 35000; |
let price: number |
const total = price * 2; |
const total: number |
const label = "Osh: " + price; |
const label: string |
const isOpen = hour >= 7 && hour < 23; |
const isOpen: boolean |
TypeScript faqat qiymatga emas, ifodaga ham qaraydi. price * 2 — ikki sonning ko'paytmasi, demak son. "Osh: " + price — satrga nimadir qo'shilyapti, demak satr. Taqqoslash va && — mantiqiy qiymat.
3.3 Funksiya natijasi ham chiqariladi
function totalPrice(price: number, quantity: number) {
return price * quantity;
}
const sum = totalPrice(35000, 2);
console.log(sum); // 70000Natija turi yozilmagan, lekin hover totalPrice ustida shuni ko'rsatadi:
function totalPrice(price: number, quantity: number): numberOxiridagi : number — natija turi. TypeScript return qatoriga qaradi: ikki sonning ko'paytmasi — son. sum ning turi ham shundan: const sum: number.
E'tibor bering: parametrlarga tur yozdik. Ularni TypeScript chiqara olmaydi — nega ekanini «Annotatsiya qayerda shart?» bo'limida ko'ramiz.
3.4 Kontekstdan chiqarish: callback parametrlari
Ba'zan TypeScript turni qiymatdan emas, joydan biladi:
const dishes = ["osh", "manti", "lag'mon"];
const upper = dishes.map((dish) => dish.toUpperCase());
console.log(upper); // [ 'OSH', 'MANTI', "LAG'MON" ]dish ga tur yozmadik. Lekin TypeScript biladi: dishes — satrlar massivi, map esa callback'ka har bir elementni beradi (Callback imzosi va HOF metodlari). Demak, dish — string. Bu kontekstli tiplash (contextual typing) deyiladi. Shu sabab callback parametrlariga tur yozish odatda shart emas.
Tur chiqarilgan bo'lsa, tekshiruv ham to'liq ishlaydi:
const dishes = ["osh", "manti", "lag'mon"];
const prices = dishes.map((dish) => dish.toFixed(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?" toFixed — sonning metodi, satrda yo'q. Qiziq joyi — maslahat. fixed satrlarning juda eski, eskirgan metodi (HTML <tt> tegini yasaydi). TypeScript shunchaki eng o'xshash nomni taklif qildi. Qoida: "Did you mean" — faqat ishora, uni ko'r-ko'rona qabul qilmang. Bu yerda haqiqiy tuzatish — narxlarni boshqa massivdan olish.
Tekshirib ko'ring:
const half = 35000 / 2;vaconst text = 35000 + " so'm";— hover'da qanday tur ko'rinadi?
Javob
const half: number — ikki sonni bo'lish son beradi (17500). const text: string — + ning bir tomoni satr bo'lsa, natija satr. TypeScript bu qoidalarni JavaScript'dan oladi: ifoda ishlaganda qanday qiymat chiqsa, turi ham shunday.
4. let va const: literal tur va kengayish
4.1 Bir xil qiymat — ikki xil tur
Ikki qatorga hover qilib ko'ramiz:
const city = "Toshkent";
let branch = "Chilonzor";
console.log(city, branch); // Toshkent Chilonzor| Kod | Hover'da |
|---|---|
const city = "Toshkent"; |
const city: "Toshkent" |
let branch = "Chilonzor"; |
let branch: string |
const hour = 9; |
const hour: 9 |
let isFree = true; |
let isFree: boolean |
const da tur — qiymatning o'zi: "Toshkent". Bu literal tur (literal type) — faqat bitta aniq qiymatdan iborat tur. const o'zgarmaydi, shuning uchun TypeScript "bu yerda doim aynan "Toshkent" turadi" deb biladi.
let da esa tur kengroq: string. Chunki let ga keyin boshqa satr yozish mumkin — branch = "Yunusobod". Agar turi "Chilonzor" bo'lsa, bunday yozuvga ruxsat bo'lmasdi. Shuning uchun TypeScript literal turni kengaytiradi (widening): "Chilonzor" → string, 9 → number, true → boolean.
O'xshatish: const — muhrlangan quti, ustida ichidagi narsaning aniq nomi yozilgan. let — qayta ishlatiladigan quti, ustida faqat "matn uchun" deb yozilgan.
4.2 Kengayish qachon seziladi?
Ko'pincha farqini sezmaysiz: "Toshkent" turidagi qiymat string kutilgan joyga bemalol beriladi. Teskarisi esa ishlamaydi. Masalan, yetkazish rejimi faqat "tez" bo'lishi mumkin bo'lgan joy:
let mode = "tez";
const fast: "tez" = mode;Kompilyator:
TS2322: Type 'string' is not assignable to type '"tez"'.Tarjimasi: "string turini "tez" turiga berib bo'lmaydi". Qiymat aynan "tez" bo'lsa ham, mode ning turi kengaygan — string. TypeScript esa qiymatga emas, turga qaraydi. let ga keyinroq "sekin" yozilishi mumkin edi.
Tuzatish — const mode = "tez";. Endi mode ning turi "tez" va xato yo'qoladi. Literal turlarni | bilan birlashtirib, "faqat shu uch qiymatdan biri" degan turlar yasash — Union va literal turlar darsining mavzusi. Hozircha bitta qoidani eslang: o'zgarmaydigan qiymat — const, bu turni ham aniqroq qiladi.
4.3 Obyekt ichida — doim kengayadi
const order = { dish: "Osh", price: 35000 };
order.price = 37000;
console.log(order); // { dish: 'Osh', price: 37000 }Sichqonchani order ustiga olib borsangiz, muharrir uning turini shunday ko'rsatadi:
const order: {
dish: string;
price: number;
}order — const, lekin xususiyatlar "Osh" va 35000 emas, string va number bo'ldi. Sababi: const faqat order nomini boshqa obyektga bog'lashni taqiqlaydi. Obyekt ichini o'zgartirish mumkin — order.price = 37000 ishladi (let va const darsidagi qoida).
TypeScript obyektning shaklini ham eslab qoldi. Unga mos kelmaydigan har narsa — xato:
const order = { dish: "Osh", price: 35000 };
order.price = "37 000";
order.discount = 10;Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.
TS2339: Property 'discount' does not exist on type '{ dish: string; price: number; }'.Ikkinchi xabar: "{ dish: string; price: number; } turida discount xususiyati yo'q". JavaScript'da obyektga yangi xususiyat istalgan payt qo'shilardi. TypeScript'da obyektning shakli yaratilgan paytda belgilanadi. Obyekt turlarini qanday yozish — Obyekt turlari darsida. Literallarni obyekt va massiv ichida ham saqlab qolish (as const) — keyingi darsda.
Tekshirib ko'ring:
let size = "katta";dan keyinsize = "kichik";yozsak, xato bo'ladimi?const size = "katta";dan keyin-chi?
Javob
let bilan — xato yo'q: tur kengaygan (string), "kichik" ham satr. const bilan — xato, lekin tur xatosi emas: const ga umuman qayta qiymat berib bo'lmaydi. TypeScript buni TS2588: Cannot assign to 'size' because it is a constant. deydi, JavaScript esa ishlash paytida TypeError beradi.
5. Annotatsiya qayerda shart?
Endi asosiy savolga qaytamiz. Qoida qisqa: TypeScript chiqara olsa — yozmang; chiqara olmasa yoki noto'g'ri chiqarsa — yozing. Uni to'rt holatga bo'lamiz.
5.1 Funksiya parametrlari — doim
function totalPrice(price, quantity) {
return price * quantity;
}Kompilyator:
TS7006: Parameter 'price' implicitly has an 'any' type.
TS7006: Parameter 'quantity' implicitly has an 'any' type.Tarjimasi: "price parametri yashirincha any turini oldi". Bu xabarni JSDoc darsida ko'rgansiz. any — "istalgan narsa, tekshirma". strict rejimda TypeScript bunga yo'l qo'ymaydi.
Nega TypeScript parametr turini chiqarmaydi? Axir totalPrice(35000, 2) chaqiruvi bor-ku? Gap shundaki, funksiya — shartnoma. Uni o'nta faylda, o'nta joyda chaqirish mumkin. TypeScript chaqiruvlarga qarab tur taxmin qilsa, bitta noto'g'ri chaqiruv butun shartnomani buzardi. Shuning uchun yo'nalish teskari: shartnoma funksiyada yoziladi, chaqiruvlar unga qarab tekshiriladi.
Tuzatish — «Funksiya natijasi ham chiqariladi» bo'limidagidek: function totalPrice(price: number, quantity: number). Callback parametrlari esa istisno — ular kontekstdan chiqariladi.
5.2 Natija turi — boshqa fayllar ishlatadigan funksiyada
Natija turini TypeScript chiqaradi. Lekin ba'zan bu xavfli. Mana yetkazib berish narxi: 10 km gacha har km 2 000 so'm, undan uzoq bo'lsa — "kelishiladi":
function deliveryFee(distanceKm: number) {
if (distanceKm > 10) return "kelishiladi";
return distanceKm * 2000;
}
const fee: number = deliveryFee(3);Kompilyator:
TS2322: Type 'number | "kelishiladi"' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.TypeScript natija turini ikkala return dan yig'di: number | "kelishiladi" — "son yoki aynan shu satr". Xato esa funksiyada emas, uni ishlatgan joyda chiqdi. Haqiqiy loyihada bu boshqa faylda, boshqa dasturchining kodida bo'lishi mumkin. U funksiyani ochib, nega satr qaytishini qidirib yuradi.
Ikkinchi qator — xabar zanjiri. Bo'sh joy bilan surilgan qator yuqoridagi xabarning sababini tushuntiradi: "aniqrog'i, satrni songa berib bo'lmaydi". Uzun xabarlarda eng pastdagi qator ko'pincha eng aniq sababni aytadi.
Endi niyatni funksiyaning o'zida yozamiz — natija turi : number:
function deliveryFee(distanceKm: number): number {
if (distanceKm > 10) return "kelishiladi";
return distanceKm * 2000;
}Kompilyator:
TS2322: Type 'string' is not assignable to type 'number'.TypeScript aytyapti: «satr turini son turiga berib bo'lmaydi» — funksiya number qaytarishga va'da bergan, bu return esa satr qaytaryapti.
Xato endi aynan buzuq return da. Muallif uni darhol ko'radi va hal qiladi: masalan, uzoq masofada RangeError tashlaydi yoki natija turini ataylab kengaytiradi. Ikkala holatda ham qaror ongli bo'ladi.
Qoida: export qilinadigan, boshqa modullar ishlatadigan funksiyalarga natija turini yozing. Bu ularning ommaviy interfeysi (public API) — boshqalar tayanadigan shartnoma. Faylning ichki yordamchi funksiyalarida natija turini chiqarishga qo'yib bersangiz bo'ladi.
5.3 Qiymatsiz e'lon — doim
«Qiymatsiz e'lon» bo'limida ko'rdik: let guestName: string;. Qiymat bo'lmasa, TypeScript turni chiqara olmaydi. Annotatsiya bilan esa u qiymat berilmagan joyni ham ushlaydi (TS2454).
5.4 Qolgan hamma joyda — odatda yozmang
// ❌ Ortiqcha: tur qiymatdan ko'rinib turibdi
const dishName: string = "Osh";
const price: number = 35000;
// ✅ Xuddi o'sha turlar, kamroq shovqin
const dishTitle = "Osh";
const dishPrice = 35000;
console.log(dishName === dishTitle, price === dishPrice); // true trueOrtiqcha annotatsiya xato emas, lekin ikki zarari bor. Birinchisi — o'qish qiyinlashadi. Ikkinchisi — const dagi aniq literal tur ("Osh") o'rniga kengroq string olinadi, ya'ni ma'lumot yo'qoladi. typescript-eslint'da bunday ortiqcha turlarni ko'rsatadigan no-inferrable-types qoidasi bor (ESLint'ni TypeScript bilan ulash — JavaScript'dan TypeScript'ga ko'chish darsida).
Butun qoidani bitta sxemada ko'ramiz. Har yangi nom uchun yuqoridan pastga savollarga javob bering:
flowchart TD
A["Yangi nom"] --> B{"Funksiya parametrimi?"}
B -- "ha, callback emas" --> Y["Tur yozing"]
B -- "yo'q" --> C{"Qiymati shu yerda bormi?"}
C -- "yo'q" --> Y
C -- "bor" --> D{"Boshqa fayl ishlatadigan<br/>funksiya natijasimi?"}
D -- "ha" --> Y
D -- "yo'q" --> N["Yozmang —<br/>TS o'zi chiqaradi"]Callback parametri (dishes.map((dish) => …)) birinchi savolda "yo'q" tomonga ketadi: u kontekstdan chiqariladi.
| Joy | Tur yozasizmi? | Nega |
|---|---|---|
| Funksiya parametri | ha | TS chaqiruvlarga qarab taxmin qilmaydi |
Qiymatsiz let |
ha | qiymat yo'q — chiqaradigan narsa yo'q |
export funksiya natijasi |
ha | xato funksiya ichida chiqadi |
| Qiymatli o'zgaruvchi | yo'q | qiymatdan aniq |
| Callback parametri | yo'q | kontekstdan aniq |
Tekshirib ko'ring:
export function vatAmount(sum: number) { return sum * 0.12; }— nimani qo'shish yaxshi?
Javob
Natija turini: export function vatAmount(sum: number): number. Parametr turi allaqachon bor. Funksiya export qilinadi — boshqa fayllar unga tayanadi. Natija turi yozilsa, kimdir keyin funksiyani o'zgartirib, tasodifan satr qaytarsa, xato boshqa faylda emas, shu funksiyaning o'zida chiqadi.
6. TypeScript nimani ushlamaydi
6.1 Annotatsiya — va'da, tekshiruv emas
Annotatsiya qiymatni o'zgartirmaydi va ishlash paytida tekshirmaydi. U faqat kompilyatorga berilgan va'da. Va'da noto'g'ri bo'lsa-chi? Saqlangan narx JSON.parse dan o'qilyapti:
const saved = '"35000"'; // saqlangan matn: ichida satr
const price: number = JSON.parse(saved);
console.log(price.toFixed(2));tsc hech qanday xato bermaydi. Node esa:
TypeError: price.toFixed is not a functionNima bo'ldi? JSON.parse ning natija turi — any ("istalgan narsa, tekshirma"). any ni istalgan turga berish mumkin, shuning uchun : number annotatsiyasi jim qabul qilindi. Aslida esa JSON.parse "35000" satrini qaytardi, satrda toFixed yo'q.
Xulosa: tashqaridan kelgan ma'lumotga (JSON, forma, server javobi, localStorage) annotatsiya yozish uni son qilib qo'ymaydi. Uni o'zingiz tekshirishingiz yoki o'zgartirishingiz kerak:
const saved = '"35000"';
const parsed: unknown = JSON.parse(saved);
const price = Number(parsed);
console.log(price.toFixed(2)); // 35000.00unknown — "hali noma'lum, avval tekshir" (JSDoc darsida ko'rgansiz). Number(...) qiymatni haqiqatan songa aylantiradi. any va unknown farqini any, unknown, never, void va object darsida to'liq o'rganamiz, server ma'lumotini tekshirishni esa API ma'lumotlarini tiplash darsida.
6.2 Annotatsiya JavaScript'ga o'tmaydi
Turlar faqat tekshiruv uchun ekanini tsc ning o'zi ko'rsatadi. Mana narx.ts:
const dishName: string = "Osh";
let price: number = 35000;
function totalPrice(price: number, quantity: number): number {
return price * quantity;
}
console.log(dishName, totalPrice(price, 2)); // Osh 70000tsc 7.0.2 shundan yasagan narx.js:
const dishName = "Osh";
let price = 35000;
function totalPrice(price, quantity) {
return price * quantity;
}
console.log(dishName, totalPrice(price, 2));
export {};Hamma : string, : number yo'qoldi — qolgani oddiy JavaScript. (export {}; — "bu fayl modul" degan belgi, uni Modullar TypeScript'da darsida ko'ramiz. 4 bo'sh joyli chekinish — tsc ning o'z uslubi.) Node 24 .ts faylni ishga tushirganda ham xuddi shunday qiladi: turlarni o'chiradi va tekshirmaydi. Shuning uchun tekshiruv faqat tsc (yoki muharrir) ishlaganda bo'ladi.
7. Ko'p uchraydigan xatolar
7.1 String katta harf bilan
let title: String = "Osh";
let label: string = title;Kompilyator:
TS2322: Type 'String' is not assignable to type 'string'.
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.Tarjimasi: "String turini string ga berib bo'lmaydi. string — primitiv, String esa o'rovchi obyekt. Imkon bo'lsa, string ishlating." String — JavaScript'dagi new String("Osh") obyektining turi. Kundalik kodda u kerak emas. Tuzatish: har doim kichik harf — string, number, boolean.
7.2 Tur o'rniga qo'shtirnoqdagi so'z
typeof natijasi satr bo'lgani uchun (typeof 5 === "number") ba'zan turni ham qo'shtirnoqda yozib qo'yishadi:
let count: "number" = 5;Kompilyator:
TS2322: Type '5' is not assignable to type '"number"'."number" — qo'shtirnoq ichida, demak bu literal tur: "faqat "number" degan satr". 5 esa son. Tuzatish: qo'shtirnoqsiz — let count: number = 5; yoki shunchaki let count = 5;.
7.3 Hamma joyga tur yozish
JavaScript'dan kelganlar ko'pincha har qatorga annotatsiya qo'yadi: const name: string = "Osh", const ok: boolean = true. Xato bermaydi, lekin kod uzayadi. Tuzatish: «Annotatsiya qayerda shart?» bo'limidagi sxema — faqat parametr, qiymatsiz e'lon va export funksiya natijasi.
7.4 Natija turini yozmaslik va xatoni uzoqdan qidirish
Xato chaqiruv joyida number | "..." kabi kutilmagan tur bilan chiqsa, sababi ko'pincha funksiyada. Tuzatish: funksiyaga natija turini yozing (deliveryFee misoli) — xato o'z joyiga ko'chadi.
8. Mashqlar
1-mashq (oson): Hover'ni oldindan ayting
Muharrir har nom uchun qaysi turni ko'rsatadi? Avval o'zingiz yozing, keyin Playground'da tekshiring.
let guests = 4;
const dish = "Manti";
let note = "achchiqsiz";
const isPaid = guests > 2;
console.log(guests, dish, note, isPaid); // 4 Manti achchiqsiz truelet guests turi: [:number]. let note turi: [:string]. const isPaid turi: .
Yechim
let guests: number, const dish: "Manti", let note: string, const isPaid: boolean. dish — const va satr literal, shuning uchun turi aynan "Manti". note — let, tur kengaygan. isPaid — taqqoslash natijasi, const bo'lsa ham boolean: TypeScript 4 > 2 ni hisoblamaydi, faqat "taqqoslash mantiqiy qiymat beradi" deb biladi.
2-mashq (o'rta): Ortiqchasini olib tashlang, kerakligini qo'shing
Kodda ham ortiqcha annotatsiya bor, ham kerakli annotatsiya yetishmaydi. tsc toza o'tadigan va eng kam tur yozilgan variantga keltiring. formatPrice boshqa fayllarda ham ishlatiladi.
const currency: string = "so'm";
const lagmonPrice: number = 28000;
export function formatPrice(amount) {
return `${amount.toLocaleString("ru-RU")} ${currency}`;
}
console.log(formatPrice(lagmonPrice));Kompilyator:
TS7006: Parameter 'amount' implicitly has an 'any' type.Ishora: toLocaleString("ru-RU") sonni bo'shliq bilan guruhlaydi (28 000) — Intl.NumberFormat darsidagi usul. Uning bo'shlig'i oddiy probel emas, uzilmas bo'sh joy, lekin ekranda farqi ko'rinmaydi.
Yechim
const currency = "so'm";
const lagmonPrice = 28000;
export function formatPrice(amount: number): string {
return `${amount.toLocaleString("ru-RU")} ${currency}`;
}
console.log(formatPrice(lagmonPrice).length); // 11currencyvalagmonPricedagi turlar olib tashlandi — qiymatdan aniq.amount: numberqo'shildi — parametrsizstrictrejimdaTS7006chiqardi.: stringnatija turi qo'shildi — funksiyaexportqilinadi, boshqa fayllar unga tayanadi.
Oxirgi qatorda matnning o'zini emas, uzunligini chiqardik: 28 000 so'm — 11 belgi, ichidagi uzilmas bo'sh joy ham bitta belgi. Konsolda uni oddiy probeldan farqlab bo'lmaydi.
3-mashq (qiyin): Amaliy tajriba — «Bahor» hisobi
Bu mashq — haqiqiy fayllarda, tsc va node --test bilan. 15-qismning hamma mashqlari bitta papkada — kurs/mashqlar/15/.
Papkani tayyorlash (bir marta). O'tgan darsda 02-ornatish/ — build qiladigan alohida loyiha edi, u o'z sozlamasi bilan qoladi. Keyingi mashqlarda build yo'q: tsc faqat tekshiradi, testlarni Node .ts dan o'zi ishga tushiradi. Ular uchun kurs/mashqlar/15/ ning o'zida bitta umumiy sozlama yaratamiz:
cd kurs/mashqlar/15
npm init -y
npm pkg set type=module
npm install --save-dev --save-exact typescript@7.0.2 @types/node@24@types/node — Node'ning turlari: node:test va node:assert ni tsc taniydi. npm init -y endi "type": "commonjs" yozadi, ikkinchi buyruq uni module ga almashtiradi. node_modules/ ni .gitignore ga qo'shishni unutmang. tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"target": "esnext",
"module": "nodenext",
"types": ["node"],
"noEmit": true,
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"erasableSyntaxOnly": true,
"moduleDetection": "force",
"skipLibCheck": true
},
"exclude": ["02-ornatish"]
}Hozircha bilishingiz kerak bo'lganlari:
strict— qat'iy rejim;types: ["node"]— Node turlari.noEmit— faqat tekshir,.jsyozma.allowImportingTsExtensions—import "./bill.ts"deb fayl nomini aynan yozishga ruxsat.exclude—02-ornatish/o'z sozlamasi bilan qoladi, bu tekshiruvga kirmaydi.
Qolganlari — tsconfig.json chuqur va Strict bayroqlar oilasi darslarida.
Endi vazifaning o'zi. 03-tur-chiqarish/bill.ts faylini yarating — bu JavaScript'dan ko'chirilgan hisob moduli:
// 03-tur-chiqarish/bill.ts — «Bahor» hisobi (JS'dan ko'chirildi)
export const SERVICE_RATE = 0.1;
export function subtotal(prices) {
let sum = 0;
for (const price of prices) {
sum += price;
}
return sum;
}
export function splitBill(total, people) {
if (people < 1) return "kamida 1 kishi";
return Math.ceil(total / people);
}npx tsc --pretty falseni ishga tushiring va xatolarni o'qing. (--pretty false— xabarlarni bir qatorda, rangsiz chiqaradi. Usiztsckod parchasi bilan rangli chiqaradi, mazmuni bir xil.)- Parametrlarga va
exportfunksiyalarning natijasiga tur yozing.prices— sonlar massivi:number[](JSDoc'dagi{number[]}bilan bir xil; massiv turlari — keyingi darsda).tscni qayta ishga tushiring — yangi xato chiqadi. Uni tuzating: 1 dan kam odam —RangeError. - Xizmat haqi funksiyasini qo'shing:
withService(sum)— summa + 10%, butun so'mgacha yaxlitlangan (Math.round). 03-tur-chiqarish/bill.test.tsdanode:testbilan testlar yozing (Birinchi avtomatik test): yig'indi (bo'sh massiv ham), xizmat haqi, bo'lish (yuqoriga yaxlitlash) va 0 kishi uchunRangeError.
Yechim
1-qadamda bizda (tsc 7.0.2) shunday chiqdi:
03-tur-chiqarish/bill.ts(4,26): error TS7006: Parameter 'prices' implicitly has an 'any' type.
03-tur-chiqarish/bill.ts(12,27): error TS7006: Parameter 'total' implicitly has an 'any' type.
03-tur-chiqarish/bill.ts(12,34): error TS7006: Parameter 'people' implicitly has an 'any' type.Uchala xato — parametr turi yo'q («Funksiya parametrlari — doim»). sum, price, SERVICE_RATE ga tur kerak emas — ular qiymatdan chiqarildi.
2-qadamda, turlar yozilgach (splitBill(...): number) — yangi, haqiqiy xato:
03-tur-chiqarish/bill.ts(13,19): error TS2322: Type 'string' is not assignable to type 'number'.Bu deliveryFee dagi holatning o'zi: funksiya ba'zan son, ba'zan satr qaytarardi. JavaScript'da "kamida 1 kishi" ni kassa summaga qo'shib, yana "0kamida 1 kishi" kabi narsa chiqarardi. Natija turi buni o'z joyida ushladi.
// 03-tur-chiqarish/bill.ts — «Bahor» hisobi
export const SERVICE_RATE = 0.1;
export function subtotal(prices: number[]): number {
let sum = 0;
for (const price of prices) {
sum += price;
}
return sum;
}
export function withService(sum: number): number {
return Math.round(sum * (1 + SERVICE_RATE));
}
export function splitBill(total: number, people: number): number {
if (people < 1) {
throw new RangeError(`Kamida 1 kishi kerak: ${people}`);
}
return Math.ceil(total / people);
}// 03-tur-chiqarish/bill.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { subtotal, withService, splitBill } from "./bill.ts";
// osh, manti va ikkita ko'k choy
const order = [35000, 30000, 5000, 5000];
test("subtotal: buyurtma yig'indisi", () => {
assert.equal(subtotal(order), 75000);
assert.equal(subtotal([]), 0);
});
test("withService: 10% xizmat haqi, butun so'm", () => {
assert.equal(withService(75000), 82500);
});
test("splitBill: 4 kishiga, yuqoriga yaxlitlab", () => {
assert.equal(splitBill(82500, 4), 20625);
assert.equal(splitBill(82500, 7), 11786);
});
test("splitBill: 0 kishi — RangeError", () => {
assert.throws(() => splitBill(82500, 0), RangeError);
});npx tsc --pretty false endi hech narsa chiqarmaydi (chiqish kodi 0). Test fayl ham tekshirildi: masalan, splitBill("82500", 4) yozsangiz, tsc TS2345 beradi. Keyin node --test — Node 24 .test.ts fayllarni o'zi topadi va turlarni o'chirib ishga tushiradi. Bizda (Node 24.21.0) shunday chiqdi, millisekundlar sizda boshqacha bo'ladi:
✔ subtotal: buyurtma yig'indisi (0.7264ms)
✔ withService: 10% xizmat haqi, butun so'm (0.1388ms)
✔ splitBill: 4 kishiga, yuqoriga yaxlitlab (0.1198ms)
✔ splitBill: 0 kishi — RangeError (0.3734ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 118.25782500 / 7 = 11 785,71…, Math.ceil uni 11 786 ga ko'taradi: mehmonlar biroz ortiqcha to'laydi, kassa kam qolmaydi. order massiviga ham tur yozmadik — number[] qiymatdan chiqarildi.
Bu darsdagi yangi xabarlarni — TS2454 (qiymat berilmagan o'zgaruvchi) va TS2551 ("Did you mean") — XATOLAR.md ga qo'shing. Keyin kurs/mashqlar papkasidan:
git add 15/package.json 15/package-lock.json 15/tsconfig.json
git add 15/03-tur-chiqarish 15/XATOLAR.md
git commit -m "15/03: bill.ts — parametr va natija turlari, testlar"9. Real ishda
- Kod ko'rib chiqishda (code review) "bu yerda tur ortiqcha" va "export funksiyaga natija turi qo'ying" — eng ko'p uchraydigan izohlardan. Ko'p jamoalarda qoida aynan shu darsdagidek: ichkarida inference, chegarada (parametr, eksport) annotatsiya.
- Hover — kundalik asbob. Tajribali dasturchi turni yodda saqlamaydi, sichqonchani olib borib ko'radi. Notanish kutubxona funksiyasi nima qaytarishini bilishning eng tez yo'li ham shu.
- Intervyu: "Type inference nima?", "Qachon tur yozish shart?", "
letvaconstturlari nega farq qiladi?" — junior TypeScript intervyusining odatiy savollari.
Xulosa
- Annotatsiya — nomdan keyin
: tur:let price: number. Asosiy turlar — kichik harf bilan:string,number,boolean. - TypeScript turni boshlang'ich qiymatdan, ifodadan,
returndan va kontekstdan (callback) o'zi chiqaradi. Muharrirda hover bilan ko'rasiz. const— literal tur ("Toshkent"),let— kengaygan tur (string). Obyekt xususiyatlariconstda ham kengayadi.- Tur yozing: parametrlarga, qiymatsiz
letga,exportfunksiyalar natijasiga. Qolgan joyda — inference'ga ishoning. - Annotatsiya qiymatni o'zgartirmaydi va ishlash paytida tekshirmaydi:
any(masalan,JSON.parse) har qanday va'dani jim qabul qiladi.
Keyingi dars: Massiv va tuple turlari — number[] va Array<number>, o'zgarmas massivlar, aniq uzunlikdagi tuple'lar va as const.
Manbalar
- TypeScript Handbook: "Everyday Types" (Type Annotations on Variables, Functions) — typescriptlang.org/docs/handbook/2/everyday-types.html
- TypeScript hujjatlari: "Type Inference" — typescriptlang.org/docs/handbook/type-inference.html
- TypeScript Handbook: "Literal Types" (literal inference,
letvaconst) — typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types - TS Playground — typescriptlang.org/play
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!