Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. JSDoc
- 2.1 Birinchi JSDoc izohi
- 2.2 Tur yozuvlari
- 2.3 O'z turingiz: @typedef
- 3. // @ts-check: tekshiruvni yoqish
- 3.1 Bitta qator
- 3.2 Terminalda: tsc
- 3.3 Uch tipik xabar
- 4. jsconfig.json: butun loyiha uchun
- 4.1 Sozlama fayli
- 4.2 strict va 73 xato
- 5. Kengroq imkoniyatlar
- 5.1 unknown va tekshiruv
- 5.2 Tur predikati
- 5.3 asserts va @throws: "qaytdimmi — demak, to'g'ri"
- 5.4 Tur o'zgartirish (cast) — qavs bilan
- 6. TypeScript'ga ko'prik
- 7. Ko'p uchraydigan xatolar
- 7.1 // @ts-check kod ostida
- 7.2 @param nomi parametrga mos emas
- 7.3 Xatoni @ts-expect-error bilan "yopish"
- 7.4 Number.isInteger tur toraytiradi deb o'ylash
- 7.5 JSDoc'ni bir marta yozib, tekshirmaslik
- 8. Mashqlar
- 1-mashq (oson): Birinchi JSDoc
- 2-mashq (o'rta): @typedef va topilgan xato
- 3-mashq (qiyin): unknown dan Booking ga
- 4-mashq: Vazifalar qadami — JSDoc va // @ts-check
- 9. Real ishda
- Xulosa
- Manbalar
JSDoc va // @ts-check: oddiy JavaScript'da turlarni tekshirish
Qisqacha: JSDoc — funksiya ustidagi
/** … */izoh: unda parametrlar va natijaning turi yoziladi (@param {number} price). Fayl boshiga// @ts-checkqo'ysangiz, VS Code bu izohlarni o'qib, noto'g'ri turdagi qiymatni kod ishga tushmasdan qizil chiziq bilan ko'rsatadi. Terminalda xuddi shu tekshiruvni TypeScript kompilyatori —tscqiladi. Kod o'zgarmaydi: u oddiy JavaScript bo'lib qoladi.
Bu darsda
- JSDoc bilan funksiya parametrlari va natijasining turini yozasiz:
@param,@returns,@type,@typedef. // @ts-checkvajsconfig.jsonbilan tur tekshiruvini yoqasiz,tscxabarlarini o'qiysiz.- "possibly 'undefined'", "implicitly has an 'any' type" kabi xatolarni tuzatasiz va turni toraytirish (narrowing) nima ekanini tushuntira olasiz.
- JSDoc va TypeScript farqini va nega bu dars TypeScript'ga eshik ekanini bilasiz.
Oldin bilishingiz kerak: ESLint va Prettier, Toza kod: funksiyalar, izohlar va tuzilma, typeof va turni to'g'ri aniqlash.
1. Nega bu kerak?
Oldingi darsda ESLint jaml kabi e'lon qilinmagan nomni ishga tushirmasdan topdi. Lekin uning ham ko'r joyi bor. Mana Sardorning yangi funksiyasi:
function totalPrice(price, quantity) {
return price * quantity;
}
console.log(totalPrice(35000, 2)); // 70000
console.log(totalPrice("35 000", 2)); // NaNIkkinchi chaqiruvda price forma maydonidan satr bo'lib keldi va ichida bo'sh joy bor. Natija — NaN (son emas). Hech qanday xato yo'q, dastur jim davom etadi va chekda "NaN so'm" chiqadi. ESLint bu yerda hech narsa demaydi: kod sintaktik jihatdan to'g'ri, hamma nom e'lon qilingan. U funksiyaga qaysi turdagi qiymat kelishini bilmaydi.
Muammoning ildizi — funksiyaning "shartnomasi" hech qayerda yozilmagan. totalPrice son kutadi, lekin buni faqat muallif biladi. Uch oydan keyin muallifning o'zi ham unutadi.
Bu darsda shartnomani izohga yozamiz va muharrirga uni tekshirishni o'rgatamiz. Kod o'sha-o'sha oddiy JavaScript bo'lib qoladi — hech qanday yangi til, yangi fayl kengaytmasi yo'q.
2. JSDoc
2.1 Birinchi JSDoc izohi
Toza kod: funksiyalar, izohlar va tuzilma darsida hujjat izohi haqida bir gap aytgan edik: /** … */ ichidagi maxsus izoh. Uning nomi — JSDoc. 08-qismda "kursda ko'rasiz" degan va'da ham shu edi (Sintaksis asoslari).
/**
* Buyurtma narxini hisoblaydi.
* @param {number} price bitta porsiya narxi, so'mda
* @param {number} quantity nechta porsiya
* @returns {number} jami narx
*/
function totalPrice(price, quantity) {
return price * quantity;
}
console.log(totalPrice(35000, 2)); // 70000Qatorma-qator:
/**— ikkita yulduzcha. Bitta yulduzchali/*oddiy izoh, uni hech kim o'qimaydi.- Birinchi qator — funksiya nima qilishi, oddiy gap bilan.
@param {number} price bitta porsiya narxi, so'mda— teg (@param; bu JSDoc tegi —@bilan boshlanadigan belgi, HTML tegi emas), jingalak qavsda tur ({number}), parametr nomi (price) va tavsif. Nomlar — Toza kod: nomlash darsidagi qoida bo'yicha inglizcha, tavsif — o'zbekcha.@returns {number} jami narx— funksiya nima qaytaradi.
Tur (type) — qiymat qaysi xilda ekani: son, satr, mantiqiy qiymat, massiv, obyekt. Siz turlarni typeof darsidan bilasiz. Farqi: typeof turni ishlash paytida so'raydi, JSDoc esa uni oldindan e'lon qiladi.
JSDoc kodning ishlashiga hech qanday ta'sir qilmaydi — bu baribir izoh. Lekin VS Code uni o'qiydi: totalPrice( deb yozishingiz bilan kichik oynada parametrlar, turlari va tavsifi chiqadi.
2.2 Tur yozuvlari
JSDoc ichidagi tur yozuvi TypeScript tilidan olingan. Ikki jadvalni yodlash shart emas — kerak bo'lganda shu yerga qaytasiz. Birinchi jadval — kundalik turlar:
| Yozuv | Ma'nosi | Misol qiymat |
|---|---|---|
{number}, {string}, {boolean} |
son, satr, mantiqiy | 35000, "Osh", true |
{string[]} |
satrlar massivi | ["osh", "manti"] |
{number | null} |
son yoki null |
4, null |
{{ name: string, price: number }} |
shu shakldagi obyekt | { name: "Osh", price: 35000 } |
Ikkinchi jadval — kamroq uchraydiganlari. Oxirgi ikkitasini «Kengroq imkoniyatlar» bo'limida misol bilan ko'ramiz:
| Yozuv | Ma'nosi | Misol qiymat |
|---|---|---|
{(d: Dish) => boolean} |
funksiya: Dish oladi, mantiqiy qaytaradi |
(d) => d.price < 30000 |
{Set<number>}, {Map<string, number>} |
to'plam, xarita | new Set([1, 2]) |
{unknown} |
"hali noma'lum — avval tekshir" | JSON.parse(...) natijasi |
{any} |
"istalgan narsa — tekshirma" | — |
Uchta yangi belgi:
|— "yoki". Bu tur birlashma (union) deyiladi:number | null— son ham,nullham bo'lishi mumkin.<number>— burchak qavsdagi tur "ichida nima bor" degani:Set<number>— sonlar to'plami.(d: Dish) => boolean— strelkali funksiyaning "sxemasi": chapda parametr va uning turi,=>dan keyin natija turi.Dish— keyingi bo'limda o'zimiz yaratadigan tur.
Ixtiyoriy parametr kvadrat qavsda yoziladi: @param {boolean} [bajarildi]. Standart qiymati bo'lsa ham shunday.
2.3 O'z turingiz: @typedef
Bir xil obyekt shakli ko'p joyda uchrasa, unga nom beriladi:
/**
* Menyudagi bitta taom.
* @typedef {object} Dish
* @property {string} name
* @property {number} price so'mda
* @property {boolean} [spicy] ixtiyoriy belgi
*/
/** @type {Dish[]} */
const menu = [
{ name: "Osh", price: 35000 },
{ name: "Lag'mon", price: 28000, spicy: true },
];
console.log(menu.length); // 2@typedef {object} Dish— "Dish(taom) degan yangi tur — obyekt".@property— uning xususiyatlari.[spicy](achchiq) — ixtiyoriy: osh obyektida u yo'q, bu xato emas./** @type {Dish[]} */— o'zgaruvchining turi:Dishlar massivi.
Endi istalgan funksiyada @param {Dish} dish deb yozasiz va muharrir dish. dan keyin name, price, spicy ni taklif qiladi.
Boshqa fayldagi turni olish uchun — @import:
/** @import { Dish } from "./menu.js" */Bu import emas, faqat izoh: ishlash paytida hech narsa yuklanmaydi.
Tekshirib ko'ring:
/* @param {number} price */(bitta yulduzcha) yozilgan funksiyaga muharrir maslahat ko'rsatadimi?
Javob
Yo'q. JSDoc faqat /** (ikki yulduzcha) bilan boshlanadigan izohda o'qiladi. Bitta yulduzchali izoh — oddiy izoh, muharrir uni e'tiborsiz qoldiradi.
3. // @ts-check: tekshiruvni yoqish
3.1 Bitta qator
JSDoc o'zi faqat maslahat beradi. Uni tekshiruvga aylantirish uchun fayl boshiga bitta izoh qo'shiladi:
// @ts-checkVS Code ichida TypeScript'ning tekshiruvchisi bor — u JavaScript fayllari uchun ham ishlaydi, hech narsa o'rnatish shart emas. Fayl boshida // @ts-check bo'lsa, u JSDoc turlarini solishtiradi va mos kelmagan joyni qizil to'lqinli chiziq bilan belgilaydi.
3.2 Terminalda: tsc
Muharrir — bitta odamning kompyuterida. Butun loyihani terminalda (va keyin CI'da) tekshirish uchun TypeScript kompilyatori — tsc kerak. U typescript paketida:
npm install --save-dev --save-exact typescript@7.0.2TypeScript 7 — kompilyatori Go tilida qayta yozilgan yangi versiya. TypeScript — JavaScript'ga turlar qo'shilgan alohida til, uni 15-qismda o'rganamiz, hozir bilish shart emas. Bugun undan faqat bitta narsa olamiz — tekshiruvchi.
price.js (1-qatori // @ts-check, keyin yuqoridagi JSDoc'li totalPrice va ikki chaqiruv) uchun:
npx tsc --noEmit --allowJs --checkJs price.js--noEmit— "hech qanday fayl yaratma, faqat tekshir". (tscaslida TypeScript'ni JavaScript'ga o'giradi, bizga bu kerak emas.)--allowJs --checkJs— ".jsfayllarni ham o'qi va tekshir".
Haqiqiy chiqish:
price.js(14,24): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.O'qilishi: price.js faylining 14-qatori, 24-ustuni; xato kodi TS2345. Tarjimasi: "string turidagi argumentni number turidagi parametrga berib bo'lmaydi". Aynan "35 000". Chiqish kodi — 1, ya'ni "xato bor". ESLint'dagi kabi, CI shu raqamga qarab tekshiruvni qizil qiladi.
Node'da shu fayl hech qanday xatosiz 70000 va NaN chiqaradi. tsc esa kodni ishga tushirmasdan, faqat izohlarga qarab topdi.
3.3 Uch tipik xabar
Endi @typedef dagi menu ga funksiya yozamiz:
/**
* @param {string} name
* @returns {number}
*/
function findPrice(name) {
const dish = menu.find((t) => t.name === name);
return dish.prise;
}Node'da findPrice("Osh") — undefined (xatosiz!). tsc:
menu.js(23,10): error TS18048: 'dish' is possibly 'undefined'.
menu.js(23,15): error TS2551: Property 'prise' does not exist on type 'Dish'. Did you mean 'price'?'dish' is possibly 'undefined'— "dishundefinedbo'lishi mumkin".findhech narsa topmasa,undefinedqaytaradi (Massivda qidirish va tekshirish).tscbuni biladi:findning natija turi —Dish | undefined. Siz esaundefinedning xususiyatini o'qimoqchisiz — menyuda yo'q taomda buTypeErrorberadi.Property 'prise' does not exist on type 'Dish'. Did you mean 'price'?— "Dishturidaprisexususiyati yo'q.priceni nazarda tutdingizmi?". Imlo xatosi —@typedeftufayli topildi.
Tuzatilgan versiya:
// @ts-check
/**
* @typedef {object} Dish
* @property {string} name
* @property {number} price so'mda
*/
/** @type {Dish[]} */
const menu = [{ name: "Osh", price: 35000 }];
/**
* @param {string} name
* @returns {number}
*/
function findPrice(name) {
const dish = menu.find((t) => t.name === name);
if (dish === undefined) {
throw new TypeError(`Menyuda yo'q: ${name}`);
}
return dish.price;
}
console.log(findPrice("Osh")); // 35000if (dish === undefined) dan keyin tsc biladi: pastda dish — aniq Dish. Bu turni toraytirish (narrowing) deyiladi: shart tekshirilgach, tur kichrayadi. typeof x === "number", x !== null, Array.isArray(x) ham toraytiradi.
Uchinchi tipik xabar — tur umuman yozilmagan parametr:
any.js(2,17): error TS7006: Parameter 'n' implicitly has an 'any' type.Tarjimasi: "n parametri yashirincha any turini oldi". any — "istalgan narsa, tekshirma". Tur yozilmagan parametr shunday bo'ladi va tsc uni ham xato deydi. Tuzatish — @param {number} n.
Tekshirib ko'ring: Nega Node'da
findPrice("Osh")xato bermayundefinedqaytardi, lekinfindPrice("Somsa")xato beradi?
Javob
"Osh" bor: dish — obyekt, uning prise xususiyati yo'q, JavaScript esa yo'q xususiyat uchun undefined qaytaradi. "Somsa" yo'q: dish ning o'zi undefined, undefined.prise esa TypeError: Cannot read properties of undefined. tsc ikkala xatoni ham kod ishga tushmasdan ko'rsatdi.
4. jsconfig.json: butun loyiha uchun
4.1 Sozlama fayli
Har safar uzun buyruq yozmaslik uchun sozlama loyiha ildizidagi jsconfig.json ga yoziladi (JSON fayl):
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2024",
"lib": ["esnext", "dom"],
"module": "esnext",
"moduleResolution": "bundler"
},
"include": ["assets/js/vazifa.js", "assets/js/royxat.js"]
}allowJs,checkJs,noEmit— yuqoridagi bayroqlar, endi faylda.strict— qat'iy rejim: yashirinanyga yo'l qo'yilmaydi,null/undefineddoim hisobga olinadi. TypeScript 7 da u standart holda yoqilgan (yozmasangiz ham), lekin faylda aniq yozib qo'yish o'quvchiga tushunarli.targetvalib— qaysi JavaScript imkoniyatlari bor deb hisoblansin.esnext— eng yangilari (Object.groupBy,toSorted),dom— brauzer API'lari (document,fetch).module,moduleResolution—importqanday o'qiladi."bundler"so'zma-so'z "yig'uvchi vosita usulida" degani:importyo'llari zamonaviy brauzer va vositalar kabi o'qiladi. Bundler'ning o'zini 16-qismda o'rganamiz, hozir bilish shart emas — shu qiymatni ko'chirib qo'yish yetarli.include— qaysi fayllar tekshiriladi. Hamma fayl emas, faqat ro'yxatdagilar — tekshiruvni asta-sekin kengaytirish uchun qulay.
checkJs: true bo'lsa, include dagi hamma fayl tekshiriladi. Unda // @ts-check qatori shart emas, lekin uni qoldirish foydali: VS Code bu faylni jsconfig.json siz ham tekshiradi va o'quvchi fayl tekshirilishini birinchi qatordan ko'radi.
Ishga tushirish:
npx tsc --noEmit -p jsconfig.json-p — "shu sozlama faylini ishlat". package.json ga skript qilib qo'yiladi.
4.2 strict va 73 xato
Mavjud loyihaga strict: true bilan tekshiruv qo'shsangiz, birinchi natija qo'rqitishi mumkin. vazifalar ning to'rt modulida, hali birorta JSDoc yo'q paytda, tsc 73 ta xato berdi. Lekin turlariga qarang:
- TS7006parametr turi yozilmagan63 xato
- TS7031destrukturlangan parametr turi yo'q4 xato
- TS7008klass maydoni any[]2 xato
- TS7053obyektga yangi kalit2 xato
- TS2339xususiyat yo'q1 xato
- TS2739majburiy xususiyatlar yetishmaydi1 xato
Manba: O'lchandi: tsc 7.0.2 --noEmit -p jsconfig.json (strict: true), vazifalar #38 holati + // @ts-check, JSDoc'siz; Node 24.21, 2026-10-05
73 tadan 69 tasi — "tur yozilmagan" (TS70xx): kod buzuq emas, faqat tsc ga shartnoma aytilmagan. Haqiqiy muammolar — oxirgi ustunlarda. strict: false bilan tekshirib ko'rsangiz, faqat bitta xato qoladi. Shuning uchun 73 ni ko'rib qo'rqmang: avval JSDoc yozasiz, keyin haqiqiy topilmalar ko'rinadi.
Maslahat: Tekshiruvni birdan hamma faylga yoqmang. Avval DOM'ga bog'lanmagan, "sof" modullarni oling (ular kamroq tur talab qiladi),
includega qo'shing va tozalang. QolganlariniTEXNIK-QARZ.mdga yozing. Bu oldingi darslardagi "qism-qism" qoidasi.
Tekshirib ko'ring:
tsc73 ta xato berdi. Bu kodda 73 ta bug bor degani-mi?
Javob
Yo'q. 69 tasi — "tur yozilmagan" xabarlari (TS70xx): kod ishlaydi, faqat tsc ga shartnoma aytilmagan. Ular JSDoc yozilgach yo'qoladi. Haqiqiy muammolar — qolgan bir nechtasi, ularni keyin birma-bir ko'rib chiqasiz.
5. Kengroq imkoniyatlar
5.1 unknown va tekshiruv
JSON.parse natijasi — server yoki foydalanuvchidan kelgan, ichida nima borligini bilmaysiz. Uni unknown deb belgilash halol:
/** @type {unknown} */
const raw = JSON.parse(text);
return raw.guests;guests.js(6,10): error TS18046: 'raw' is of type 'unknown'.Tarjimasi: "raw — unknown turida". unknown qiymatning xususiyatini o'qib bo'lmaydi — avval tekshirish kerak. Bu kuchli himoya: paketniOqi dagi kabi tekshiruvni unutsangiz, tsc eslatadi.
5.2 Tur predikati
Tekshiruvni alohida funksiyaga olsangiz, tsc ga u nimani isbotlashini aytish kerak:
/**
* @param {unknown} qiymat
* @returns {qiymat is Record<string, unknown>}
*/
function oddiyObyektmi(qiymat) {
return (
typeof qiymat === "object" &&
qiymat !== null &&
!Array.isArray(qiymat)
);
}@returns {qiymat is Record<string, unknown>} — tur predikati (type predicate): "true qaytarsam, qiymat — kalitlari satr bo'lgan obyekt". Record<string, unknown> — "kalitlari satr, qiymatlari hali noma'lum obyekt" degani. if (oddiyObyektmi(x)) ichida tsc x ni shunday deb biladi. Bu vazifalar ning paket.js idan. Funksiya nomi "-mi" bilan tugashi (Toza kod: nomlash) ham predikat ekanini aytib turibdi.
5.3 asserts va @throws: "qaytdimmi — demak, to'g'ri"
Predikat true/false qaytaradi va siz uni if ichida ishlatasiz. Ba'zi tekshiruvchi funksiyalar esa hech narsa qaytarmaydi: qiymat noto'g'ri bo'lsa, xato tashlaydi. Ularga assertion ("tasdiqlash") turi yoziladi:
// @ts-check
/**
* Qiymat satr bo'lmasa, xato tashlaydi.
* @param {unknown} value
* @returns {asserts value is string}
* @throws {TypeError} satr bo'lmasa
*/
function assertString(value) {
if (typeof value !== "string") {
throw new TypeError("Satr kutilgan edi");
}
}
/** @type {unknown} */
const input = JSON.parse('"Osh"');
assertString(input);
console.log(input.toUpperCase()); // OSH@returns {asserts value is string}— "funksiya xatosiz qaytsa,value— satr". Shu chaqiruvdan pastdatscinputni satr deb biladi.assertString(input);qatorini o'chirsangiz,tscoxirgi qatorda'input' is of type 'unknown'(TS18046) deydi.@throws {TypeError}— "bu funksiyaTypeErrortashlashi mumkin".tscbuni tekshirmaydi, bu o'quvchi uchun hujjat: funksiyani chaqirgan odamtry...catchkerakmi-yo'qmi biladi.
vazifalar dagi malumotlarniTekshir — aynan shunday assertion funksiya (Vazifalar qadamida ko'rasiz).
5.4 Tur o'zgartirish (cast) — qavs bilan
Ba'zan siz tsc dan ko'proq bilasiz. Masalan, fetch faqat Error tashlashini bilasiz, lekin catch dagi qiymat unknown. Unda tur "aytib qo'yiladi":
const { name } = /** @type {Error} */ (error);Qavs majburiy. Qavssiz yozilsa, tsc izohni e'tiborsiz qoldiradi:
cast.js(5,34): error TS18046: 'error' is of type 'unknown'.Cast — "menga ishon" degani. Uni kam ishlating va yoniga nega ishonish mumkinligini izoh qilib yozing.
Tekshirib ko'ring:
JSON.parsenatijasini{any}emas,{unknown}deb belgilash nega yaxshiroq?
Javob
any — "tekshirma": raw.guests ni xatosiz o'qishga ruxsat beradi, guests yo'q bo'lsa, xato faqat ishlash paytida chiqadi. unknown — "avval tekshir": typeof, in yoki predikat bilan shaklini isbotlamaguningizcha tsc xususiyatni o'qitmaydi. Ya'ni tekshiruvni unutish imkoni qolmaydi.
6. TypeScript'ga ko'prik
Yuqoridagi totalPrice TypeScript tilida shunday yoziladi (.ts fayl):
function totalPrice(price: number, quantity: number): number {
return price * quantity;
}Turlar izohda emas, kodning o'zida: price: number. G'oya bir xil — o'sha tekshiruvchi, o'sha xabarlar (TS2345). Farqi:
JSDoc + @ts-check |
TypeScript (.ts) |
|
|---|---|---|
| Fayl | oddiy .js, brauzer to'g'ridan-to'g'ri ishlatadi |
.ts, avval JavaScript'ga o'giriladi |
| Yozuv | izohda, uzunroq | kodda, qisqa |
| Boshlash | bitta qator qo'shiladi | loyiha sozlanadi |
| Imkoniyatlar | ko'pi bor | to'liq |
Ba'zi jamoalar ataylab JSDoc'da qoladi — masalan, Svelte freymvorki 2023-yilda o'z kodini TypeScript fayllaridan JSDoc'li JavaScript'ga o'tkazgan: o'girish bosqichisiz ishlash qulayroq bo'lgani uchun. Ko'pchilik loyihalar esa TypeScript'da. Bu darsda o'rgangan hamma narsa — tur yozuvlari, unknown, toraytirish, predikat — 15-qismda to'g'ridan-to'g'ri kerak bo'ladi.
flowchart LR
A["JSDoc izohlari<br/>@param, @typedef"] --> B["TypeScript<br/>tekshiruvchisi"]
B --> C["VS Code:<br/>qizil chiziq"]
B --> D["tsc --noEmit:<br/>terminal va CI"]
A -.-> E["Node va brauzer:<br/>izohni o'qimaydi"]Diagrammaga qarang: izoh ikki yo'ldan boradi. Tekshiruvchi uni o'qiydi va xatolarni ko'rsatadi. Kodni ishga tushiradigan Node va brauzer esa uni oddiy izoh deb tashlab yuboradi — tur xatosi bo'lsa ham kod ishlayveradi. Tekshiruv faqat siz uni ishga tushirganingizda ishlaydi.
7. Ko'p uchraydigan xatolar
7.1 // @ts-check kod ostida
const a = 1;
// @ts-checkTekshiruv ishlamaydi — tsc hech narsa demaydi. Tuzatish: // @ts-check faylning eng boshida, birinchi koddan oldin bo'lsin.
7.2 @param nomi parametrga mos emas
name.js(2,21): error TS8024: JSDoc '@param' tag has name 'pric', but there is no parameter with that name.Tarjimasi: "JSDoc'dagi @param tegida pric nomi bor, lekin bunday parametr yo'q". Parametrni qayta nomlaganda izohni unutish — tez-tez uchraydi. Tuzatish: izohdagi nomni ham o'zgartiring. VS Code'dagi "Rename Symbol" (F2) ikkalasini birga o'zgartiradi.
7.3 Xatoni @ts-expect-error bilan "yopish"
// @ts-expect-error — "keyingi qatorda xato kutilyapti, ko'rsatma". Keyingi qatorda xato bo'lmay qolsa, tsc buni ham aytadi:
kut.js(8,1): error TS2578: Unused '@ts-expect-error' directive.Tarjimasi: "Ishlatilmagan @ts-expect-error direktivasi". Bu ESLint'dagi eslint-disable-next-line ning tur tekshiruvidagi o'xshashi. Qoida: faqat haqiqatan zarur joyda, sababi bilan. Xatoni "yopish" emas, tuzatish kerak.
7.4 Number.isInteger tur toraytiradi deb o'ylash
id — unknown bo'lsa, !Number.isInteger(id) || id < 1 da tsc id < 1 ni qabul qilmaydi (TS18046). Number.isInteger true qaytarsa ham, tsc id son ekanini bilmaydi. Tuzatish: oldiga typeof id !== "number" || qo'shing. Ishlash paytidagi natija bir xil, tsc esa endi ishonadi.
7.5 JSDoc'ni bir marta yozib, tekshirmaslik
// @ts-check va tsc yo'q bo'lsa, JSDoc oddiy izoh: kod o'zgaradi, izoh esa eskicha qoladi va yolg'on gapira boshlaydi. Tuzatish: JSDoc yozilgan joyda tekshiruv ham bo'lsin (npm run tip yoki CI).
8. Mashqlar
1-mashq (oson): Birinchi JSDoc
Funksiyaga JSDoc yozing: name — satr, guests — son, time — ixtiyoriy satr; funksiya satr qaytaradi.
function bookingText(name, guests, time = "19:00") {
return `${name}: ${guests} kishi, soat ${time}`;
}
console.log(bookingText("Malika", 4)); // Malika: 4 kishi, soat 19:00Yechim
// @ts-check
/**
* Bron haqida bir qatorli matn yasaydi.
* @param {string} name mehmon ismi
* @param {number} guests necha kishi
* @param {string} [time] "SS:DD", standart — "19:00"
* @returns {string}
*/
function bookingText(name, guests, time = "19:00") {
return `${name}: ${guests} kishi, soat ${time}`;
}
console.log(bookingText("Malika", 4)); // Malika: 4 kishi, soat 19:00[time] — kvadrat qavs: ixtiyoriy parametr. Endi bookingText("Malika", "4") deb yozsangiz, VS Code "4" ostiga qizil chiziq tortadi.
2-mashq (o'rta): @typedef va topilgan xato
Quyidagi kodga Order (buyurtma) turini yozing (dish — satr, quantity — son, note — ixtiyoriy satr) va // @ts-check qo'shing. tsc qanday xato topadi? Tuzating.
const orders = [
{ dish: "Osh", quantity: 2 },
{ dish: "Manti", quantity: 3, note: "achchiqsiz" },
];
function totalPortions(list) {
return list.reduce((sum, b) => sum + b.quantty, 0);
}
console.log(totalPortions(orders)); // NaNYechim
// @ts-check
/**
* @typedef {object} Order
* @property {string} dish
* @property {number} quantity
* @property {string} [note]
*/
/** @type {Order[]} */
const orders = [
{ dish: "Osh", quantity: 2 },
{ dish: "Manti", quantity: 3, note: "achchiqsiz" },
];
/**
* @param {Order[]} list
* @returns {number}
*/
function totalPortions(list) {
return list.reduce((sum, b) => sum + b.quantity, 0);
}
console.log(totalPortions(orders)); // 5b.quantty da tsc aytadi: Property 'quantty' does not exist on type 'Order'. Did you mean 'quantity'?. Node esa undefined ni qo'shib, jim NaN berardi. reduce ning sum va b parametrlariga tur yozish shart emas — tsc ularni list turidan o'zi chiqaradi.
3-mashq (qiyin): unknown dan Booking ga
Saqlangan matndan bronni o'qiydigan funksiya yozing. JSON.parse natijasi unknown bo'lsin; shakli to'g'ri bo'lsa — { name, guests }, aks holda null. tsc xatosiz o'tsin.
Ishora: turni qadamma-qadam toraytiring — avval typeof raw === "object" va null emasligi, keyin "name" in raw (in operatori — xususiyat bormi, Obyekt: kalit-qiymat juftliklari), keyin typeof raw.name.
Yechim
// @ts-check
/**
* @typedef {object} Booking
* @property {string} name
* @property {number} guests 1 dan 20 gacha
*/
/**
* Saqlangan matndan bronni o'qiydi; shakli noto'g'ri bo'lsa — null.
* @param {string} text
* @returns {Booking | null}
*/
function parseBooking(text) {
/** @type {unknown} */
const raw = JSON.parse(text);
if (typeof raw !== "object" || raw === null) return null;
if (!("name" in raw) || typeof raw.name !== "string") return null;
if (!("guests" in raw) || typeof raw.guests !== "number") {
return null;
}
return { name: raw.name, guests: raw.guests };
}
console.log(parseBooking('{"name":"Malika","guests":4}'));
console.log(parseBooking('{"name":"Malika","guests":"4"}')); // null
console.log(parseBooking("null")); // nullKonsolda:
{ name: 'Malika', guests: 4 }
null
nullHar if turni bir qadam toraytiradi: object va null emas → "name" in raw bilan name xususiyati bor → typeof bilan u satr. Oxirgi qatorda tsc hamma maydon to'g'ri turda ekanini biladi. Yangi obyekt qaytarilgani ham muhim: raw dagi ortiqcha maydonlar natijaga o'tmaydi (oq ro'yxat g'oyasi).
4-mashq: Vazifalar qadami — JSDoc va // @ts-check
vazifalar ning to'rt sof modulini (DOM'ga bog'lanmaganlarini) tur tekshiruviga ulaymiz.
- Branch:
chore/jsdoc-ts-check - Commit:
chore: sof modullarga JSDoc turlari va // @ts-check; npm run tip
npm install --save-dev --save-exact typescript@7.0.2;package.jsonga"tip": "tsc --noEmit -p jsconfig.json".jsconfig.json— «jsconfig.json: butun loyiha uchun» bo'limidagi fayl:allowJs,checkJs,noEmit,strict: true,target: es2024,lib: ["esnext", "dom"](Object.groupBy,Set.prototype.difference,toSorteduchun),module: esnext,moduleResolution: bundler.include— faqat to'rt sof modul:vazifa.js,royxat.js,paket.js,api.js(har birining 1-qatori// @ts-check).- JSDoc:
@typedef VazifaMalumoti(vazifa.js), boshqa modullarda/** @import { VazifaMalumoti } from "./vazifa.js" */;@param/@returnshamma funksiyada;@typedef SorovSozlamasi/IchkiSozlama(api.js); tur predikati@returns {qiymat is Record<string, unknown>}(oddiyObyektmi); assertion@returns {asserts malumotlar is VazifaMalumoti[]}(malumotlarniTekshir);@throws {VazifaXatosi}.
Avval faqat 1–2-qadamni bajarib (// @ts-check va jsconfig.json, JSDoc'siz), npm run tip ni ishga tushiring. Keyin JSDoc yozing va haqiqiy xatolarni tuzating.
Yechim
tsc — oldin (// @ts-check va jsconfig.json, JSDoc'siz): strict: true da 73 xato — 63×TS7006 (parametr turi yo'q), 4×TS7031, 2×TS7008 (#vazifalar, #tinglovchilar — any[]), 2×TS7053, 1×TS2339, 1×TS2739. Chiqishdan parcha:
assets/js/api.js(55,5): error TS7053: Element implicitly has an 'any' type because expression of type '"Content-Type"' can't be used to index type '{ Accept: string; }'.
assets/js/api.js(56,11): error TS2339: Property 'body' does not exist on type '{ method: string; headers: { Accept: string; }; signal: AbortSignal; }'.
assets/js/royxat.js(37,3): error TS7008: Member '#vazifalar' implicitly has an 'any[]' type.strict: false da — 1 ta:
assets/js/api.js(86,33): error TS2739: Type '{}' is missing the following properties from type '{ kutish?: number; metod?: string; signal: any; tana: any; }': signal, tanaTarjimasi: "{} turida quyidagi xususiyatlar yetishmaydi: signal, tana". sorovYubor(url, sozlama = {}) dagi bo'sh obyekt sorovniTayyorla ga beriladi, tsc esa uning parametrlari turini destrukturlashdan chiqargan — standart qiymati yo'q signal va tana majburiy bo'lib qolgan.
Haqiqiy xatolar (implicit any emas) va tuzatish:
| Xato | Sabab | Tuzatish | Xulq |
|---|---|---|---|
api.js TS2739 sorovYubor(url, sozlama = {}) |
sorovniTayyorla({ … }) parametrlari turi destrukturdan chiqarilgan: signal, tana majburiy bo'lib qolgan |
@typedef SorovSozlamasi / IchkiSozlama — hammasi ixtiyoriy |
o'zgarmadi |
api.js TS7053 sorov.headers["Content-Type"] = …, TS2339 sorov.body = … |
obyekt literali turi keyin qo'shiladigan xususiyatni bilmaydi | /** @type {RequestInit & { headers: Record<string, string> }} */ const sorov |
o'zgarmadi |
royxat.js TS2532 ×2 this.top(id).almashtir(), this.top(id).matnniOzgartir(matn) — "Object is possibly 'undefined'" (JSDoc @returns {Vazifa | undefined} qo'yilgach chiqdi) |
noma'lum id'da undefined.almashtir() |
#topYokiXato(id) — throw new TypeError(`Vazifa topilmadi: id ${id}`) |
xato turi o'sha (TypeError, #35 testi o'zgarmay o'tdi), matni tushunarli; UI bu yo'lga bormaydi. Test endi matnni ham tekshiradi |
| Xato | Sabab | Tuzatish | Xulq |
|---|---|---|---|
paket.js TS18046 'v.id' is of type 'unknown' + TS2345 ×2 (v.id < 1, idlar.has/add(v.id)) — vazifaniOl Record<string, unknown> qaytargach |
Number.isInteger turni toraytirmaydi |
shartga typeof v.id !== "number" || qo'shildi |
mantiqan bir xil (Number.isInteger raqam bo'lmaganda baribir false) |
api.js tarmoqXatosi(xato) — catch qiymati unknown |
— | const { name } = /** @type {Error} */ (xato); (izoh: fetch faqat Error tashlaydi) |
bir xil (null bo'lsa ikkalasi ham TypeError) |
Jadvallardagi ikki yangi yozuv: RequestInit — fetch ning ikkinchi argumenti (sozlamalar obyekti) turi, u jsconfig.json dagi dom dan keladi. & — "va": RequestInit & { headers: … } — ikkala turning xususiyatlari birga. | "yoki" bo'lsa, & — "ham".
Eng qiziq topilma — royxat.js da. top(id) ga @returns {Vazifa | undefined} yozilishi bilan tsc ikki joyni ko'rsatdi: noma'lum id kelsa, undefined.almashtir() — tushunarsiz TypeError. Tuzatish:
// UI faqat ekrandagi id bilan chaqiradi: noma'lum id — dasturchi
// xatosi. Avval undefined'dan tushunarsiz TypeError chiqardi
/** @param {number} id */
#topYokiXato(id) {
const vazifa = this.top(id);
if (vazifa === undefined) {
throw new TypeError(`Vazifa topilmadi: id ${id}`);
}
return vazifa;
}
/** @param {number} id */
almashtir(id) {
this.#topYokiXato(id).almashtir();
this.#xabarBer();
}Xulq o'zgarmadimi? Xato turi o'sha — TypeError, Birinchi avtomatik test darsidagi qotiruvchi test (assert.throws(..., TypeError)) o'zgarmay o'tdi. Faqat matn tushunarli bo'ldi, test endi uni ham tekshiradi:
test("noma'lum id — TypeError, sababi aytiladi", () => {
const xato = {
name: "TypeError",
message: "Vazifa topilmadi: id 99",
};
assert.throws(() => yangiRoyxat().almashtir(99), xato);
assert.throws(() => yangiRoyxat().matnniOzgartir(99, "A"), xato);
});paket.js dagi tuzatish — «Number.isInteger tur toraytiradi deb o'ylash» xatosining aynan o'zi:
if (
typeof v.id !== "number" ||
!Number.isInteger(v.id) ||
v.id < 1 ||
idlar.has(v.id)
) {Keyin: npm run tip — chiqishsiz, exit 0. npm test — 59/59, lint, format:check toza.
TEXNIK-QARZ.md: 6-qator "to'landi (12/#39)" — chizib qo'yildi, yonida: // @ts-check topdi, endi TypeError: Vazifa topilmadi: id N. Yangi 10-qator (9-qator — nomlash qarzi, u Legacy kod va texnik qarz darsidan beri bor) ikki narsani yozadi:
// @ts-checkfaqat 4 modulda (vazifa,royxat,paket,api); qolgan oltitasi va testlar tekshirilmaydi;javobniOqiserver JSON'inianydeb qaytaradi — shaklinipaketniOqiish vaqtida tekshiradi.
Bu Legacy kod va texnik qarz darsidagi qoida: qarz to'landi va ro'yxatdan ko'rinib turibdi, yangi qarz esa yashirilmadi.
README v3.1 ga yangilandi (npm install, lint/format/tip, TEXNIK-QARZ.md havolasi). .gitignore: node_modules/.
git switch -c chore/jsdoc-ts-check
npm install --save-dev --save-exact typescript@7.0.2
# jsconfig.json, // @ts-check, JSDoc, tuzatishlar
npm run tip && npm test && npm run lint && npm run format:check
git add .
git commit -m "chore: sof modullarga JSDoc turlari va // @ts-check; \
npm run tip"
git push -u origin chore/jsdoc-ts-check
gh pr create --fill
gh pr merge --mergeShu qadam bilan vazifalar v3.1 tayyor: to'rtta tekshiruv (npm test, npm run lint, npm run format:check, npm run tip) va brauzer ssenariysi 45/45 — ilova xulqi #08 dagi bilan bir xil.
9. Real ishda
- Katta JavaScript loyihalarida JSDoc +
checkJs— TypeScript'ga o'tishning birinchi bosqichi: fayllar.jsbo'lib qoladi, tekshiruv esa modulma-modul kengayadi. - Kutubxonalar hujjati. npm'dagi ko'p paketlarning hujjat sayti JSDoc izohlaridan avtomatik yasaladi. Siz VS Code'da ko'rgan paket maslahatlari ham shunday izohlardan (yoki
.d.tstur fayllaridan) keladi. - CI'da
npm run tiphamlintvatestqatorida turadi — tur xatosi bilan PR birlashtirilmaydi. - TypeScript bugun frontend va Node vakansiyalarining katta qismida talab qilinadi. Nega TypeScript darsidan boshlab 15-qism shu tilga bag'ishlangan; bugungi
@typedefu yerdatypevainterfacega aylanadi. - Intervyu: "
anyvaunknownfarqi?", "Narrowing nima?", "JSDoc bilan TypeScript'siz tur tekshirsa bo'ladimi?" — tez-tez so'raladi.
Xulosa
- JSDoc —
/** … */dagi turli izoh:@param {tur} nom,@returns,@type,@typedef+@property,@import. U kodni o'zgartirmaydi. // @ts-check(fayl boshida) VS Code'da tekshiruvni yoqadi;tsc --noEmit -p jsconfig.json— terminal va CI uchun. Kod ishga tushmasdan"35 000"kabi noto'g'ri turni topadi.strictda tur yozilmagan parametr —TS7006; mavjud loyihada birinchi natija katta bo'ladi, lekin haqiqiy topilmalar ozchilik.undefinedbo'lishi mumkin bo'lgan qiymat vaunknownavval tekshiriladi — bu turni toraytirish (if, predikat yokiasserts). Cast (/** @type {…} */ (x)) — qavs bilan va kam.- JSDoc — TypeScript'ning o'sha tekshiruvchisi, faqat izohda. 15-qismda turlar kodning o'ziga ko'chadi.
Keyingi dars: JavaScript'ning mashhur tuzoqlari — butun kurs davomida uchragan eng xavfli tuzoqlarni bitta ro'yxatga yig'amiz va qaysi birini qaysi vosita ushlashini ko'ramiz.
Manbalar
- TypeScript hujjatlari: "JSDoc Reference", "Type Checking JavaScript Files", "What is a jsconfig.json" — typescriptlang.org/docs
- TypeScript blogi: "A 10x Faster TypeScript" (2025-03) — devblogs.microsoft.com/typescript
- JSDoc — jsdoc.app
- VS Code hujjatlari: "JavaScript type checking" — code.visualstudio.com/docs/languages/javascript
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!