Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tur predikati: value is T
- 2.1 Natija turi — "agar true bo'lsa, bu Dish"
- 2.2 else da ham ishlaydi
- 2.3 filter bilan: aralash massivdan aniq tur
- 2.4 Predikat qoidalari
- 3. TypeScript 5.5: predikat o'zi chiqariladi
- 3.1 Natija turi yozilmasa
- 3.2 Qachon chiqarilmaydi
- 4. Assertion funksiyalar: asserts
- 4.1 asserts value is T — "qaytdimmi, demak to'g'ri"
- 4.2 asserts condition — shart haqida
- 4.3 Qoida: aniq tur yozilgan nom bilan chaqirish
- 5. Predikatmi yoki assertion?
- 6. TypeScript nimani ushlamaydi: yolg'onchi predikat
- 7. Ko'p uchraydigan xatolar
- 7.1 boolean natijali tekshiruv funksiyasi
- 7.2 Predikat turi parametrga sig'maydi
- 7.3 Strelka funksiyali assertion
- 7.4 Yarim tekshiruvli predikat
- 8. Mashqlar
- 1-mashq (oson): Natija turini to'ldiring
- 2-mashq (o'rta): Booking predikati va filter
- 3-mashq (qiyin): Amaliy tajriba — menyu faylini o'qish
- 9. Real ishda
- Xulosa
- Manbalar
TypeScript custom type guard va assertion funksiyalar: x is T va asserts
Qisqacha: Tur predikati — natija turi
value is Dishbo'lgan funksiya:trueqaytarsa, TypeScriptvalueniDishdeb biladi. Shunday qilib uzun tekshiruvni bir marta yozib, hamma joydaif (isDish(x))bilan ishlatasiz. Assertion funksiya (asserts value is Dish) esabooleanqaytarmaydi: noto'g'ri bo'lsa xato tashlaydi, qaytsa — tur toraygan. TypeScript bu funksiyalar ichini tekshirmaydi: predikat yolg'on gapirsa, tur ham yolg'on bo'ladi.
Bu darsda
- Tekshiruvni funksiyaga chiqarasiz va
value is Tbilan uni toraytiradigan qilasiz. - Predikatni
filterbilan ishlatib,unknown[]dan aniq turdagi massiv olasiz. - TypeScript 5.5 dan beri predikatlar qachon o'zi chiqarilishini bilasiz.
asserts value is Tvaasserts conditionassertion funksiyalarini yozasiz.- Predikat va assertion'ni qachon tanlashni va ularning xavfini tushunasiz.
Oldin bilishingiz kerak: Discriminated union va to'liqlik tekshiruvi, Narrowing: turni toraytirish, any, unknown, never, void va object.
1. Nega bu kerak?
Nega TypeScript darsida va'da bergan edik: unknown qiymatning maydonlarini tekshirishni qulay funksiyaga aylantiramiz. Mana o'sha tekshiruv — «Bahor» menyusi fayldan o'qilyapti:
type Dish = { name: string; price: number };
const value: unknown = JSON.parse('{"name":"Osh","price":35000}');
if (
typeof value === "object" &&
value !== null &&
"name" in value &&
typeof value.name === "string" &&
"price" in value &&
typeof value.price === "number"
) {
console.log(`${value.name}: ${value.price}`); // Osh: 35000
}Ishlaydi — o'tgan darslardagi toraytirishlarning hammasi bir shartda. Lekin bu olti qatorni menyu, bron va chek fayllarini o'qiydigan har joyda takrorlash kerak. Tabiiy fikr — funksiyaga chiqarish:
type Dish = { name: string; price: number };
function isDish(value: unknown): boolean {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
"price" in value
);
}
const value: unknown = JSON.parse('{"name":"Osh","price":35000}');
if (isDish(value)) {
console.log(value.name);
}Kompilyator:
TS18046: 'value' is of type 'unknown'.TypeScript aytyapti: «value ning turi — unknown», ya'ni "hali hech narsa bilmayman". Tekshiruv funksiya ichida bo'ldi, lekin if ichida value hali ham unknown. Natija turi boolean TypeScript'ga faqat "ha yoki yo'q" deydi — nimaga "ha" ekanini emas. Bu bilimni funksiyadan tashqariga chiqarish uchun maxsus natija turi kerak. (Bu yerda : boolean ni o'zimiz yozdik. Yozmasak, TypeScript ba'zan predikatni o'zi chiqaradi — «TypeScript 5.5: predikat o'zi chiqariladi» bo'limida.)
2. Tur predikati: value is T
2.1 Natija turi — "agar true bo'lsa, bu Dish"
type Dish = { name: string; price: number };
function isDish(value: unknown): value is Dish {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
typeof value.name === "string" &&
"price" in value &&
typeof value.price === "number"
);
}
const value: unknown = JSON.parse('{"name":"Osh","price":35000}');
if (isDish(value)) {
console.log(`${value.name}: ${value.price}`); // Osh: 35000
}value is Dish — tur predikati (type predicate). O'qilishi: "bu funksiya true qaytarsa, value — Dish". Funksiya ichi oddiy boolean qaytaradi, lekin chaqiruvchi uchun natija endi toraytiruvchi. JSDoc darsida xuddi shu narsani @returns {qiymat is Record<string, unknown>} shaklida ko'rgansiz — bu uning TypeScript yozuvi.
Turni toraytiradigan har qanday tekshiruv — typeof, in, instanceof va shunday funksiya — tur qo'riqchisi (type guard) deyiladi: unknown darsidagi eshikdagi qorovul kabi: hujjatni tekshiradi va faqat to'g'ri qiymatni ichkariga o'tkazadi. O'zimiz yozgani — custom type guard (o'z tur qo'riqchimiz).
Shartnoma shunday: "TypeScript, tekshirishni men bajardim, natijamga ishon". Nomi odatda is… yoki o'zbekcha "-mi" bilan tugaydi — isDish, xabarmi (predikat nomlari).
2.2 else da ham ishlaydi
Predikat ikki tomonga toraytiradi. Parametr union bo'lsa, false tarmog'ida Dish chiqarib tashlanadi:
type Dish = { name: string; price: number };
type Drink = { name: string; hot: boolean };
function isDish(item: Dish | Drink): item is Dish {
return "price" in item;
}
function line(item: Dish | Drink): string {
if (isDish(item)) {
return `${item.name}: ${item.price} so'm`;
}
return `${item.name} (${item.hot ? "issiq" : "sovuq"})`;
}
const tea = { name: "Ko'k choy", hot: true };
console.log(line(tea)); // Ko'k choy (issiq)else (bu yerda if dan keyingi qism) da item — Drink. Bu in bilan toraytirish bilan bir xil, faqat endi tekshiruvning nomi bor va uni qayta ishlatish mumkin.
2.3 filter bilan: aralash massivdan aniq tur
Predikatning eng qulay joyi — massivni filtrlash:
type Dish = { name: string; price: number };
function isDish(value: unknown): value is Dish {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
typeof value.name === "string" &&
"price" in value &&
typeof value.price === "number"
);
}
const raw: unknown[] = JSON.parse(
'[{"name":"Osh","price":35000},{"name":"?"},null]',
);
const dishes = raw.filter(isDish);
console.log(dishes.length, dishes[0]?.price); // 1 35000Hover: const dishes: Dish[]. filter ning predikat qabul qiladigan varianti bor: callback value is Dish bo'lsa, natija — Dish[]. Oddiy boolean callback'da esa natija unknown[] bo'lib qolardi.
2.4 Predikat qoidalari
TypeScript predikatning ichini tekshirmaydi, lekin ikki qoidaga qaraydi. Birinchisi — predikat turi parametr turiga sig'ishi kerak:
function isFree(price: string | number): price is boolean {
return price === 0;
}Kompilyator:
TS2677: A type predicate's type must be assignable to its parameter's type.
Type 'boolean' is not assignable to type 'string | number'.string | number qiymat hech qachon boolean bo'la olmaydi — predikat ma'nosiz. Bu xabarni type va interface qadamida vazifalar da ko'rgan edik (interface VazifaMalumoti bilan). Ikkinchi qoida — funksiya boolean qaytarishi shart: return 1 — TS2322.
Tekshirib ko'ring:
function isText(x: unknown): x is string { return true; }—tscxato beradimi?isText(5)dan keyin nima bo'ladi?
Javob
tsc xato bermaydi: natija boolean, predikat turi (string) unknown ga sig'adi. Lekin funksiya yolg'on gapiradi — 5 uchun ham true. if (isText(5)) ichida TypeScript 5 ni satr deb hisoblaydi, .toUpperCase() esa ishlash paytida TypeError beradi. Bu xavf haqida — «TypeScript nimani ushlamaydi» bo'limida.
3. TypeScript 5.5: predikat o'zi chiqariladi
3.1 Natija turi yozilmasa
TypeScript 5.5 (2024-yil iyun) dan beri sodda tekshiruv funksiyalarida predikatni yozish shart emas — kompilyator uni o'zi chiqaradi (inferred type predicates). tsc --declaration ko'rsatgan turlar:
| Funksiya | Chiqarilgan natija turi |
|---|---|
function isText(x: unknown) { return typeof x === "string"; } |
x is string |
(x: string | null) => x !== null |
x is string |
function isText(x: unknown): boolean { … } |
boolean (o'zingiz yozdingiz) |
(x: number | null) => x !== null && x > 0 |
boolean |
Eng ko'p sezadigan joy — filter:
const tips = [5000, null, 10000, null];
const real = tips.filter((tip) => tip !== null);
console.log(real.reduce((sum, tip) => sum + tip, 0)); // 15000Hover: const real: number[]. TypeScript 5.5 gacha bu (number | null)[] edi va sum + tip xato berardi. Endi callback'dan tip is number chiqarildi.
3.2 Qachon chiqarilmaydi
Jadvaldagi oxirgi qator: x !== null && x > 0. Nega predikat chiqmadi? Predikat ikki tomonlama va'da: true — "bu number", false — "bu number emas". x > 0 qo'shilgach, false endi null ni ham, -5 ni ham bildiradi. "false — demak null" deyish yolg'on bo'lardi, shuning uchun TypeScript boolean qoldirdi. Bunday holatda filtrlangan massiv (number | null)[] bo'lib qoladi.
Uchta qoidani eslang: natija turi yozilmagan, parametr funksiya ichida qayta yozilmagan va tekshiruv ikki tomonlama to'g'ri. Murakkabroq holatda predikatni o'zingiz yozing — u kodni o'qiyotgan odamga ham niyatni aytadi.
4. Assertion funksiyalar: asserts
4.1 asserts value is T — "qaytdimmi, demak to'g'ri"
Predikat if bilan ishlatiladi: "agar shunday bo'lsa…". Ba'zan esa boshqa narsa kerak: "shunday bo'lishi shart, aks holda davom etmaymiz". Fayl import qilinyapti — buzuq bo'lsa, butun import to'xtashi kerak:
type Dish = { name: string; price: number };
function assertDish(value: unknown): asserts value is Dish {
if (
typeof value !== "object" ||
value === null ||
!("name" in value) ||
typeof value.name !== "string" ||
!("price" in value) ||
typeof value.price !== "number"
) {
throw new TypeError("Taom yozuvi buzuq");
}
}
const value: unknown = JSON.parse('{"name":"Manti","price":30000}');
assertDish(value);
console.log(value.price + 5000); // 35000asserts value is Dish — assertion funksiya: "bu funksiya xatosiz qaytsa, value — Dish". Funksiya boolean qaytarmaydi — u void, noto'g'ri qiymatda esa throw qiladi. Chaqiruvdan keyingi hamma qatorlarda value — Dish. if yo'q, chekinish yo'q — kod tekis davom etadi. JSDoc darsidagi @returns {asserts value is string} ning TypeScript shakli.
4.2 asserts condition — shart haqida
Ikkinchi ko'rinishi turni emas, shartni tasdiqlaydi:
function check(
condition: unknown,
message: string,
): asserts condition {
if (!condition) {
throw new Error(message);
}
}
function seatsLeft(total: number | null, taken: number): number {
check(total !== null, "Zal sig'imi noma'lum");
return total - taken;
}
console.log(seatsLeft(40, 12)); // 28check(total !== null, …) dan keyin TypeScript shartni rost deb biladi: total — number. Node'ning node:assert modulidagi assert funksiyasi ham aynan shunday turlangan (asserts value):
import assert from "node:assert/strict";
function lastPrice(prices: readonly number[]): number {
const last = prices.at(-1);
assert(last !== undefined, "Narxlar ro'yxati bo'sh");
return last;
}
console.log(lastPrice([35000, 28000])); // 28000prices.at(-1) — oxirgi element yoki undefined (bo'sh massivda). assert dan keyin last — number, shuning uchun return last natija turiga mos. Testlarda ham shunday: assert.ok(item !== undefined) dan keyingi qatorlarda item toraygan bo'ladi. O'z check funksiyangiz bilan node:assert farqi — faqat xato turi va xabarida.
4.3 Qoida: aniq tur yozilgan nom bilan chaqirish
Assertion funksiyani strelka funksiya qilib yozsangiz, bir talab bor:
type Dish = { name: string; price: number };
const assertDish = (value: unknown): asserts value is Dish => {
if (typeof value !== "object") throw new TypeError("buzuq");
};
const v: unknown = JSON.parse("{}");
assertDish(v);Kompilyator:
TS2775: Assertions require every name in the call target to be declared with an explicit type annotation.Tarjimasi: "Assertion'lar chaqiruvdagi har bir nom aniq tur annotatsiyasi bilan e'lon qilinishini talab qiladi". const assertDish = … — o'zgaruvchining turi qiymatdan chiqarilgan, aniq yozilmagan. TypeScript kod oqimini tahlil qilayotganda chiqarilgan turlarni hisoblamaydi. Tuzatish: function assertDish(…) e'loni (eng sodda) yoki o'zgaruvchiga tur yozish.
Tekshirib ko'ring: Nega
assertDishdan xatosiz qaytgachvalueDishbo'ladi, lekin funksiyaning natija turivoidkabi hech narsa qaytarmaydi?
Javob
Assertion funksiya ma'lumotni natija orqali emas, qaytish fakti orqali beradi. Noto'g'ri qiymatda u throw qiladi va keyingi qatorlarga yetib bo'lmaydi. Demak, keyingi qatorga yetib kelgan bo'lsak — tekshiruv o'tgan. TypeScript kod oqimi tahlilida shuni hisobga oladi (never — "qaytmaydigan" funksiya bilan bir mantiq).
5. Predikatmi yoki assertion?
flowchart TD
A["Qiymatni tekshirish kerak"] --> B{"Noto'g'ri bo'lsa<br/>davom etish mumkinmi?"}
B -- "ha: tashlab yuborish,<br/>boshqa yo'l" --> P["Predikat: value is T<br/>if (isDish(x)) …, filter(isDish)"]
B -- "yo'q: to'xtash kerak" --> S["Assertion: asserts value is T<br/>assertDish(x); keyin x — T"]Predikat x is T |
Assertion asserts x is T |
|
|---|---|---|
| Natija | boolean |
qaytadi yoki throw |
| Ishlatilishi | if, filter, find |
alohida qator |
| Noto'g'ri qiymatda | false — boshqa tarmoq |
xato tashlanadi |
| Qayerda | ro'yxatdan yaroqlilarini ajratish | kirish nuqtasi: import, sozlama, test |
vazifalar da ikkalasi ham bor (hali JSDoc'da, paket.js da): oddiyObyektmi — predikat (qiymat is Record<string, unknown>), malumotlarniTekshir — assertion (asserts malumotlar is VazifaMalumoti[]). Import qilingan faylda bitta buzuq vazifa bo'lsa, butun import rad etiladi — shuning uchun assertion. Eslang: type va interface qadamidagi TS2677 aynan shu assertion'da chiqqan edi. Discriminated union qadamida esa birinchi .ts predikat — sinxron.ts dagi xabarmi(malumot: unknown): malumot is SinxronXabar — paydo bo'ldi. paket moduli API ma'lumotlarini tiplash qadamida .ts ga o'tadi va bu JSDoc'lar TypeScript yozuviga aylanadi.
6. TypeScript nimani ushlamaydi: yolg'onchi predikat
Predikat — sizning va'dangiz. TypeScript uni tekshirmaydi, faqat ishonadi:
type Dish = { name: string; price: number };
// Xato: faqat name tekshirilgan, price — yo'q
function isDish(value: unknown): value is Dish {
return (
typeof value === "object" && value !== null && "name" in value
);
}
const value: unknown = JSON.parse('{"name":"Osh"}');
if (isDish(value)) {
console.log(value.price.toFixed(0));
}tsc — xatosiz. Node esa:
TypeError: Cannot read properties of undefined (reading 'toFixed')Predikat price ni tekshirmadi, lekin "bu Dish" dedi. TypeScript value.price ni son deb hisobladi. Bu as (tur majburlash, keyingi darsda) kabi xavfli: kompilyatorning ishonchini siz boshqarasiz.
Himoya:
- Predikat turning hamma majburiy maydonlarini tekshirsin. Tur o'zgarsa (yangi maydon), predikatni ham yangilang — buni test bilan mustahkamlang.
- Predikatlarni bir joyda saqlang (masalan, tur yonida) va ularga alohida test yozing.
- Murakkab sxemalar uchun tekshiruvni turdan avtomatik yasaydigan kutubxonalar bor — Zod darsida.
7. Ko'p uchraydigan xatolar
7.1 boolean natijali tekshiruv funksiyasi
function isDish(x: unknown): boolean — chaqiruvchi uchun toraymaydi (TS18046). Tuzatish: x is Dish.
7.2 Predikat turi parametrga sig'maydi
(price: string | number): price is boolean — TS2677. Tuzatish: predikat turi parametr turining bir qismi bo'lsin.
7.3 Strelka funksiyali assertion
const assertX = (…): asserts … => … — chaqiruvda TS2775. Tuzatish: function assertX(…).
7.4 Yarim tekshiruvli predikat
Bitta maydonni tekshirib, butun turni va'da qilish — TypeError ishlash paytida. Tuzatish: hamma majburiy maydonlar va test.
8. Mashqlar
1-mashq (oson): Natija turini to'ldiring
Predikat natijasi: x [:is] string — "true bo'lsa, x satr". Noto'g'ri qiymatda xato tashlaydigan funksiya natijasidagi kalit so'z: [:asserts]. Strelka funksiya qilib yozilgan assertion chaqirilganda chiqadigan xato kodi: TS.
Yechim
x is string— tur predikati:booleanqaytaradi,trueda toraytiradi.asserts— assertion funksiya: qaytsa — to'g'ri, aks holdathrow. Shart uchun shakli —asserts condition.TS2775— assertion'ni chaqirishda nom aniq tur bilan e'lon qilingan bo'lishi kerak;functione'loni bu talabni o'zi bajaradi.
2-mashq (o'rta): Booking predikati va filter
Bron yozuvi: type Booking = { guest: string; people: number; time: string }. isBooking(value: unknown): value is Booking yozing (hamma maydon, people — 1 dan katta yoki teng butun son). Keyin JSON'dan o'qilgan aralash massivdan faqat yaroqli bronlarni ajrating va ularning odamlar sonini yig'ing.
Ishora: Number.isInteger toraytirmaydi (Narrowing darsi) — undan oldin typeof … === "number" yozing.
Yechim
type Booking = { guest: string; people: number; time: string };
function isBooking(value: unknown): value is Booking {
return (
typeof value === "object" &&
value !== null &&
"guest" in value &&
typeof value.guest === "string" &&
"people" in value &&
typeof value.people === "number" &&
Number.isInteger(value.people) &&
value.people >= 1 &&
"time" in value &&
typeof value.time === "string"
);
}
const raw: unknown[] = JSON.parse(
'[{"guest":"Malika","people":2,"time":"19:00"},' +
'{"guest":"Bobur","people":0,"time":"20:00"},' +
'{"guest":"Dilshod aka","people":4,"time":"20:30"}]',
);
const bookings = raw.filter(isBooking);
const people = bookings.reduce((sum, b) => sum + b.people, 0);
console.log(bookings.length, people); // 2 6raw ga unknown[] deb tur yozdik: JSON.parse ning any ini darhol to'xtatdik. filter(isBooking) — Booking[], keyingi reduce da b.people — son. Boburning broni (0 kishi) tashlab yuborildi.
3-mashq (qiyin): Amaliy tajriba — menyu faylini o'qish
Mashq kurs/mashqlar/15/ da. Birinchi variant — boolean natijali tekshiruv:
// 13-guards/menu.ts — menyu faylini o'qish (birinchi variant)
export type MenuItem = {
readonly name: string;
readonly price: number;
};
export function isMenuItem(value: unknown): boolean {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
typeof value.name === "string" &&
"price" in value &&
typeof value.price === "number"
);
}
export function parseMenu(json: string): MenuItem[] {
const data: unknown = JSON.parse(json);
if (!Array.isArray(data)) {
throw new TypeError("Menyu massiv emas");
}
const items: unknown[] = data;
return items.filter(isMenuItem);
}npx tsc --pretty false— xatoni o'qing. Negaconst items: unknown[] = data;qatori kerak bo'ldi? (Ishora:Array.isArrayniunknownga qo'llasangiz, natija turi qanday? Hover qiling.)isMenuItemni predikatga aylantiring. Qo'shimcha talab: nomi bo'sh bo'lmasin, narx — musbat butun son.assertMenu(value: unknown): asserts value is MenuItem[]yozing: massiv emas —TypeError("Menyu massiv emas"), N-yozuv buzuq —TypeError("N-yozuv buzuq").parseMenuuni ishlatsin — bitta buzuq yozuv butun faylni rad etsin.validItems(values)— yumshoq variant: buzuqlarni tashlab yuboradi.- Testlar: 6 xil noto'g'ri yozuv, yaroqli fayl, ikki xil
TypeError(xabari bilan),validItems.
Yechim
1-qadamda tsc 7.0.2:
13-guards/menu.ts(24,3): error TS2322: Type 'unknown[]' is not assignable to type 'MenuItem[]'.
Type 'unknown' is not assignable to type 'MenuItem'.boolean callback bilan filter turni o'zgartirmaydi: unknown[] → unknown[]. items: unknown[] qatori nega kerak? Array.isArray(data) dan keyin data ning turi — any[] (tsc --declaration buni any[] deb ko'rsatadi). Bu — standart kutubxonadagi eski qaror. any[] bilan filter natijasi ham any[] bo'lardi va MenuItem[] ga jim mos kelardi — xato yashirinardi. unknown[] ga olib, any ni darhol to'xtatdik.
// 13-guards/menu.ts — menyu faylini o'qish
export type MenuItem = {
readonly name: string;
readonly price: number;
};
// Tur predikati: true qaytsa — value MenuItem
export function isMenuItem(value: unknown): value is MenuItem {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
typeof value.name === "string" &&
value.name.trim() !== "" &&
"price" in value &&
typeof value.price === "number" &&
Number.isInteger(value.price) &&
value.price > 0
);
}
// Assertion: qaytsa — hammasi yaroqli; bitta buzuq yozuv — xato
export function assertMenu(
value: unknown,
): asserts value is MenuItem[] {
if (!Array.isArray(value)) {
throw new TypeError("Menyu massiv emas");
}
value.forEach((item: unknown, index) => {
if (!isMenuItem(item)) {
throw new TypeError(`${index + 1}-yozuv buzuq`);
}
});
}
export function parseMenu(json: string): MenuItem[] {
const data: unknown = JSON.parse(json);
assertMenu(data);
return data;
}
// Yumshoq variant: buzuq yozuvlarni tashlab yuboradi
export function validItems(values: readonly unknown[]): MenuItem[] {
return values.filter(isMenuItem);
}assertMenu(data);dan keyinreturn data;—dataendiMenuItem[], hech qandayassiz.forEach((item: unknown, index) => …)—itemgaunknowndeb tur yozdik, aks holda uanybo'lardi (any[]ning elementi).- Ikki xil xulq ikki funksiyada:
parseMenu— qat'iy (assertion),validItems— yumshoq (predikat +filter). Qaysi biri kerakligi vaziyatga bog'liq: menyu importi — qat'iy, kunlik statistika — yumshoq.
// 13-guards/menu.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { isMenuItem, parseMenu, validItems } from "./menu.ts";
test("isMenuItem: to'g'ri va noto'g'ri yozuvlar", () => {
assert.equal(isMenuItem({ name: "Osh", price: 35000 }), true);
const bad = [
null,
"Osh",
{ name: "Osh" },
{ name: " ", price: 5000 },
{ name: "Manti", price: "30000" },
{ name: "Choy", price: -5000 },
];
for (const value of bad) {
assert.equal(isMenuItem(value), false);
}
});
test("parseMenu: yaroqli fayl", () => {
const menu = parseMenu('[{"name":"Osh","price":35000}]');
assert.equal(menu[0]?.price, 35000);
});
test("parseMenu: massiv emas va buzuq yozuv — TypeError", () => {
assert.throws(() => parseMenu('{"name":"Osh"}'), {
name: "TypeError",
message: "Menyu massiv emas",
});
const json = '[{"name":"Osh","price":35000},{"name":"Somsa"}]';
assert.throws(() => parseMenu(json), {
name: "TypeError",
message: "2-yozuv buzuq",
});
});
test("validItems: buzuqlari tashlanadi", () => {
const items = validItems([{ name: "Osh", price: 35000 }, null, {}]);
assert.deepEqual(items, [{ name: "Osh", price: 35000 }]);
});assert.throws ning ikkinchi argumenti — obyekt: xato nomi va xabari tekshiriladi. menu[0]?.price — mashqlar papkasida noUncheckedIndexedAccess yoqilgan (Massiv va tuple). npx tsc --pretty false — chiqishsiz. node --test 13-guards/menu.test.ts — bizda (Node 24.21.0):
✔ isMenuItem: to'g'ri va noto'g'ri yozuvlar (1.7419ms)
✔ parseMenu: yaroqli fayl (0.5174ms)
✔ parseMenu: massiv emas va buzuq yozuv — TypeError (1.5751ms)
✔ validItems: buzuqlari tashlanadi (1.257ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 291.7513XATOLAR.md ga: TS2677 (predikat turi), TS2775 (strelkali assertion), TS2322 'unknown[]' … 'MenuItem[]'. Keyin kurs/mashqlar papkasidan:
git add 15/13-guards 15/XATOLAR.md
git commit -m "15/13: menu.ts — is va asserts bilan tekshiruv"9. Real ishda
- Kirish nuqtalari — server javobi,
localStorage,postMessage, fayl importi — predikat va assertion'larning asosiy joyi. Ichkaridagi kod esa allaqachon tekshirilgan turlar bilan ishlaydi. - Testlarda
assert(x !== undefined)(node:assert) va Vitest/Jest'dagi shunga o'xshash funksiyalar —assertsning kundalik ko'rinishi. - Kutubxonalar: Zod'ning
schema.parse()— aslida avtomatik yasalgan assertion: o'tsa — tur aniq, o'tmasa — xato (Zod). - Intervyu: "Type guard nima va qanday yoziladi?", "
isvaassertsfarqi?", "TS 5.5 dagi inferred type predicates nima?" — o'rta darajadagi savollar.
Xulosa
value is T— tur predikati:trueqaytsa, chaqiruvchi uchunvalue—T.if,else,filter,findbilan ishlaydi.- TypeScript 5.5 dan beri sodda tekshiruvlarda predikat o'zi chiqariladi (
filter((x) => x !== null)→ aniq tur), lekin faqat ikki tomonlama to'g'ri bo'lsa. asserts value is T— qaytsa, keyingi qatorlardavalue—T; noto'g'ri bo'lsathrow.asserts condition— shartni tasdiqlaydi. Strelka emas,functionbilan yozing (TS2775).- Predikat — va'da: TypeScript ichini tekshirmaydi. Yarim tekshiruv — ishlash paytidagi
TypeError. Hamma maydon va test. - Kirishda — assertion (qat'iy) yoki predikat +
filter(yumshoq).
Keyingi dars: Type assertion, non-null va satisfies — as bilan TypeScript'ni "ishontirish", ! operatori va turini yo'qotmasdan tekshiradigan satisfies.
Manbalar
- TypeScript Handbook: "Narrowing" → Using type predicates, Assertion functions — typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
- TypeScript Release Notes 3.7 (assertion functions) — typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
- TypeScript Release Notes 5.5 ("Inferred Type Predicates", 2024-06) — typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html
- Node.js hujjatlari:
assert(value[, message])— nodejs.org/api/assert.html
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!