IlmHamroh
JavaScript Full-stack/15-qism. TypeScript11/47-dars17 daqiqa
Mundarija (33)

TypeScript narrowing: turni toraytirish — typeof, in, instanceof va tekshiruvlar

Qisqacha: Narrowing (toraytirish) — TypeScript tekshiruvdan keyin keng turni aniqroq turga o'zi aylantirishi. value: string | number bo'lsa, if (typeof value === "string") { … } ichida value — string, undan keyin esa — number. TypeScript buni kod oqimini kuzatib qiladi: typeof, if (x), === null, "key" in obj va instanceof — hammasi turni toraytiradi.

Bu darsda

  • TypeScript kodni qanday "o'qishini" — kod oqimi tahlilini tushunasiz.
  • Beshta toraytirish usulini ishlatasiz: typeof, truthiness, tenglik, in, instanceof.
  • typeof null === "object" va if (qty) dagi 0 tuzoqlarini taniysiz.
  • "Qolgani" qoidasini bilasiz: tekshirilmagan variantlar ham toraytiriladi.
  • Toraytirish qayerda yo'qolishini (callback, qayta yozish) va qanday saqlab qolishni ko'rasiz.

Oldin bilishingiz kerak: Strukturaviy tiplash, Union va literal turlar, typeof va turni to'g'ri aniqlash.

1. Nega bu kerak?

Union darsida ko'rdik: string | number qiymat bilan faqat umumiy narsalar qilinadi, qolgani uchun — "avval tekshiring". unknown darsida ham shu qoida edi. Lekin bu qanday ishlaydi? Qaysi tekshiruvni TypeScript tushunadi, qaysi birini — yo'q?

Sardor kassa ekranidagi stol yozuvini chiqaradi. Stol raqami son (7), VIP xona nomi satr ("vip-2") yoki hali tanlanmagan (null) bo'lishi mumkin:

js
function tableLabel(table) {
  return table.toUpperCase();
}

console.log(tableLabel("vip-2")); // VIP-2

Son yoki null berilsa — TypeError. JavaScript'da qaysi tekshiruvni unutganingizni faqat ishlab turgan dastur aytadi. TypeScript esa har qatorda table hozir nima bo'lishi mumkinligini biladi.

2. Kod oqimi tahlili

2.1 Turni qatorma-qator kuzatish

ts
function tableLabel(table: string | number | null): string {
  if (table === null) {
    return "Stol tanlanmagan";
  }
  if (typeof table === "number") {
    return `Stol ${table}`;
  }
  return table.toUpperCase();
}

console.log(tableLabel(null)); // Stol tanlanmagan
console.log(tableLabel(7)); // Stol 7
console.log(tableLabel("vip-2")); // VIP-2

Har qatorda table ning turi boshqa:

Joy table turi
funksiya boshida string | number | null
birinchi if ichida null
birinchi if dan keyin string | number
ikkinchi if ichida number
oxirgi return da string

TypeScript har if, return va else ni kuzatib boradi. Birinchi if dan keyin null yo'q — chunki null bo'lsa, funksiya allaqachon qaytgan bo'lardi. Bu kod oqimi tahlili (control flow analysis). Kundalik o'xshatish — bojxona: har nazorat nuqtasidan keyin yo'lovchilar oqimi torayadi. Oxirgi eshikka faqat hamma tekshiruvdan o'tganlar yetib keladi.

flowchart TD
  A["table: string | number | null"] --> B{"table === null ?"}
  B -- "ha" --> N["null → 'Stol tanlanmagan'"]
  B -- "yo'q" --> C["string | number"]
  C --> D{"typeof table === 'number' ?"}
  D -- "ha" --> M["number → 'Stol 7'"]
  D -- "yo'q" --> S["string → toUpperCase()"]

2.2 "Qolgani" ham toraytiriladi

Oxirgi qatorda biz table satr ekanini tekshirmadik. TypeScript uni o'zi chiqardi: null ham, number ham chiqarib tashlandi, union'da faqat string qoldi. Variantlar kamayib borib, oxirida bittasi qolsa — tekshiruv shart emas.

Tekshirib ko'ring: Jadvaldagi birinchi if ni if (table === null) { console.log("tanlanmagan"); } ga almashtirsak (return siz), oxirgi table.toUpperCase() qatorida nima bo'ladi?

Javob

TS18047: 'table' is possibly 'null'. return bo'lmasa, null holati if dan chiqib, pastga davom etadi — oqim torayadi, lekin faqat if ichida. Toraytirish "bu yo'ldan keyin qaysi qiymatlar yetib keladi?" savoliga javob: return (yoki throw) bo'lmasa, yetib keladi.

Hamma variant chiqarib tashlansa, qiymat turi never bo'ladi (o'tgan dars). Bundan "hamma variantni ko'rib chiqdimmi?" degan tekshiruv yasaladi — Discriminated union va to'liqlik tekshiruvi darsida.

3. typeof bilan toraytirish

3.1 Primitivlar uchun

typeof qaytaradigan satrlar (typeof darsi): "string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function". TypeScript ularning har birini tushunadi va union'dan mos a'zoni ajratadi.

ts
function formatQty(qty: number | string): string {
  if (typeof qty === "string") {
    return qty.trim();
  }
  return qty.toFixed(0);
}

console.log(formatQty(" 3 "), formatQty(2.4)); // 3 2

3.2 Tuzoq: typeof null === "object"

JavaScript'ning eski xatosi TypeScript'da ham bor — va TypeScript uni biladi:

ts
function countItems(items: string[] | null) {
  if (typeof items === "object") {
    return items.length;
  }
  return 0;
}

Kompilyator:

text
TS18047: 'items' is possibly 'null'.

Tarjimasi: "items null bo'lishi mumkin". Massiv ham, null ham typeof da "object" beradi. Shuning uchun if ichida tur string[] | null bo'lib qoldi. TS18047 — TS18048 ning qarindoshi: biri null haqida, ikkinchisi undefined haqida. Tuzatish: if (items !== null) yoki Array.isArray(items) — ikkalasi ham toraytiradi.

3.3 Tayyor tekshiruv funksiyalari

Ba'zi standart funksiyalar ham toraytiradi, chunki ularning turida "bu tekshiruv" deb yozilgan. Eng ko'p uchraydigani — Array.isArray(x): true bo'lsa, x — massiv. Number.isInteger va Number.isFinite esa toraytirmaydi — JSDoc darsida shu tuzoqqa duch kelgan edik: unknown ni Number.isInteger bilan tekshirsangiz ham, u unknown bo'lib qoladi. Ularning oldidan typeof x === "number" yozing. O'zingiz ham shunday "toraytiradigan" funksiya yasay olasiz — Custom type guard darsida.

4. Truthiness: if (x)

4.1 null, undefined va bo'sh qiymatlar

if (x) — "x truthy (rost hisoblanadigan) bo'lsa" (Boolean va truthy/falsy). Falsy qiymatlar: false, 0, "", null, undefined, NaN. TypeScript bu qoidani biladi: if (note) ichida note dan undefined va null chiqarib tashlanadi.

ts
function noteLine(note?: string): string {
  if (note) {
    return `Izoh: ${note.trim()}`;
  }
  return "Izohsiz";
}

console.log(noteLine("piyozsiz")); // Izoh: piyozsiz
console.log(noteLine()); // Izohsiz

Bo'sh satr ham shu yerda "izohsiz" bo'ldi — bu holatda aynan kerak narsa.

4.2 Tuzoq: 0 ham falsy

Sonlarda esa if (x) xavfli. Chegirma foizi ixtiyoriy:

ts
function discountText(percent?: number): string {
  if (percent) {
    return `Chegirma: ${percent}%`;
  }
  return "Chegirma belgilanmagan";
}

console.log(discountText(10)); // Chegirma: 10%
console.log(discountText(0)); // Chegirma belgilanmagan

tsc — xatosiz, lekin natija noto'g'ri: Jasur aka "chegirma — 0%" deb aniq belgilagan, ekranda esa "belgilanmagan". TypeScript tur jihatidan to'g'ri toraytirdi (if ichida percent — number), lekin 0 ni "yo'q" qilib tashlaganingizni xato deb bilmaydi. Qoida: son va satrda "bormi?" degan savol uchun !== undefined yozing:

ts
function discountText(percent?: number): string {
  if (percent !== undefined) {
    return `Chegirma: ${percent}%`;
  }
  return "Chegirma belgilanmagan";
}

console.log(discountText(0)); // Chegirma: 0%

Tekshirib ko'ring: function seats(n: number | null) { if (n) return n * 2; return 0; } — seats(0) va seats(null) nima qaytaradi? Qaysi biri xato?

Javob

Ikkalasi ham 0. seats(null) uchun to'g'ri, seats(0) uchun esa tasodifan to'g'ri — chunki 0 * 2 ham 0. Lekin if (n) "nol" va "yo'q" ni bir xil ko'radi. Formula n + 1 bo'lsa, seats(0) 1 o'rniga 0 berardi. Aniq yozuv: if (n !== null).

5. Tenglik bilan toraytirish

5.1 === null, === undefined va == null

=== bilan aniq qiymatga solishtirish uni union'dan ajratadi yoki chiqarib tashlaydi. Bitta qulay istisno: x == null (ikki teng belgi) — null va undefined ni birga tekshiradi. Bu == ning yagona keng tarqalgan foydali ishlatilishi (Tenglik: ==, === va Object.is):

ts
function guestName(name: string | null | undefined): string {
  if (name == null) {
    return "Mehmon";
  }
  return name;
}

console.log(guestName(null), guestName(undefined)); // Mehmon Mehmon
console.log(guestName("Malika")); // Malika

5.2 Literal qiymat bilan

ts
type Size = "yarim" | "to'liq";

function portionPrice(size: Size, fullPrice: number): number {
  if (size === "yarim") {
    return fullPrice * 0.6;
  }
  return fullPrice;
}

console.log(portionPrice("yarim", 35000)); // 21000

if dan keyin size — faqat "to'liq". switch (size) { case "yarim": … } ham xuddi shunday toraytiradi. Literal union va switch — keyingi darsning asosiy vositasi.

5.3 Ikki union'ni solishtirish

Kamdan-kam, lekin chiroyli holat:

ts
function sameCode(a: string | number, b: string | boolean): string {
  if (a === b) {
    return a.toUpperCase() + b.toUpperCase();
  }
  return "farq";
}

console.log(sameCode("osh", "osh"), sameCode(1, true)); // OSHOSH farq

a === b bo'lsa, ikkalasi bir xil qiymat — demak, bir xil tur. Ikki union'ning umumiy a'zosi faqat string. TypeScript if ichida ikkalasini ham string ga toraytirdi.

6. in bilan toraytirish

Obyektlar union'ida typeof yordam bermaydi — hammasi "object". Ularni xususiyat borligi bo'yicha ajratish mumkin (in operatori):

ts
type Dish = { name: string; cookMinutes: number };
type Drink = { name: string; hot: boolean };

function waitTime(item: Dish | Drink): string {
  if ("cookMinutes" in item) {
    return `${item.name}: ${item.cookMinutes} daqiqa`;
  }
  return `${item.name}: darhol`;
}

const osh = { name: "Osh", cookMinutes: 40 };
const tea = { name: "Choy", hot: true };
console.log(waitTime(osh)); // Osh: 40 daqiqa
console.log(waitTime(tea)); // Choy: darhol

"cookMinutes" in item — rost bo'lsa, item — Dish (union'da bu xususiyat faqat unda bor). Yolg'on bo'lsa — Drink. in o'tgan darsdagi strukturaviy fikrlashga mos: "qaysi tur" emas, "qanday xususiyati bor" deb so'raymiz.

in ning bir xavfi bor. Ikkala turda ham ixtiyoriy bo'lgan xususiyat bo'yicha toraytirish ishonchsiz: "note" in x ham, unga teskari holat ham ikkala turga tegishli bo'lishi mumkin. Aniq farqlovchi kerak bo'lsa — maxsus maydon (kind: "dish"), bu ham keyingi darsda.

7. instanceof bilan toraytirish

Klass obyektlarini instanceof ajratadi:

ts
function when(value: Date | string): string {
  if (value instanceof Date) {
    return value.toISOString().slice(0, 10);
  }
  return value;
}

const opening = new Date("2026-03-21T09:00:00Z");
console.log(when(opening), when("ertaga")); // 2026-03-21 ertaga

Eng ko'p joyi — catch dagi xato (o'tgan dars): if (error instanceof RangeError) … else if (error instanceof Error) …. Esda tuting: instanceof prototip zanjirini tekshiradi. Strukturaviy tiplash darsida ko'rganimizdek, klass turiga mos oddiy obyekt instanceof dan o'tmaydi.

Usul Nimani ajratadi Misol
typeof primitivlar, funksiya typeof x === "string"
truthiness null, undefined (va 0, ""!) if (note)
tenglik aniq qiymat, null x === null, x == null
in obyektlar — xususiyati bo'yicha "hot" in item
instanceof klass obyektlari x instanceof Date

Tekshirib ko'ring: function len(x: string | string[]) { … } — uzunlikni emas, birinchi belgini (yoki birinchi elementni) qaytarish kerak. Qaysi toraytirish usulini tanlaysiz?

Javob

typeof x === "string" — x[0] satrning birinchi belgisi; aks holda x — string[], x[0] birinchi element. Array.isArray(x) ham ishlaydi — TypeScript uni ham tushunadi. instanceof Array ham bo'ladi, lekin boshqa oyna (iframe) massivlarida ishlamaydi — Array.isArray xavfsizroq.

8. Toraytirish qachon yo'qoladi

TypeScript toraytirishni xavfsiz bo'lganda saqlaydi. Qiymat tekshiruvdan keyin o'zgarishi mumkin bo'lsa — unutadi.

8.1 Obyekt xususiyati va callback

ts
function printLater(order: { note?: string }) {
  if (order.note !== undefined) {
    setTimeout(() => console.log(order.note.toUpperCase()), 0);
  }
}

Kompilyator:

text
TS18048: 'order.note' is possibly 'undefined'.

TypeScript aytyapti: «order.note undefined bo'lishi mumkin» — callback ichida u if tekshiruvini "unutdi".

if tekshirdi, lekin callback keyinroq bajariladi (setTimeout). Ungacha kimdir order.note = undefined qilishi mumkin — obyekt umumiy. TypeScript callback ichida xususiyat toraytirishini qayta tiklaydi. Tuzatish: qiymatni const ga oling — const o'zgarmaydi, uning toraytirishi callback ichida ham saqlanadi:

ts
function printLater(order: { note?: string }) {
  const note = order.note;
  if (note !== undefined) {
    setTimeout(() => console.log(note.toUpperCase()), 0);
  }
}

printLater({ note: "achchiqsiz" });

Konsolda:

text
ACHCHIQSIZ

8.2 Keyin qayta yoziladigan let

let o'zgaruvchi tekshiruvdan keyin funksiyada qayta yozilsa, callback ichida toraytirish yo'qoladi:

ts
function remind(initial?: string) {
  let note = initial;
  if (note !== undefined) {
    setTimeout(() => console.log(note.trim()), 0);
  }
  note = undefined;
}

Kompilyator:

text
TS18048: 'note' is possibly 'undefined'.

TypeScript aytyapti: «note undefined bo'lishi mumkin».

Callback note = undefined qatoridan keyin bajariladi — o'sha paytda note haqiqatan undefined. TypeScript bu xavfni ko'rdi. Oxirgi qatorni o'chirsangiz, xato yo'qoladi: qayta yozish bo'lmasa, toraytirish callback ichida ham saqlanadi (TypeScript 5.4 dan beri). Qoida: callback ishlatadigan qiymatni const ga oling — eng sodda va doim ishlaydi.

9. Ko'p uchraydigan xatolar

9.1 typeof x === "object" — null ni unutish

TS18047: 'x' is possibly 'null'. Tuzatish: x !== null && qo'shing yoki Array.isArray.

9.2 Sonda if (x)

0 "yo'q" bo'lib qoladi, tsc jim. Tuzatish: x !== undefined yoki x != null.

9.3 Tekshiruvni funksiyaga chiqarib, natijasini boolean deb yozish

function isText(x: unknown): boolean { return typeof x === "string"; } — if (isText(v)) ichida v toraymaydi. boolean natija TypeScript'ga faqat "ha yoki yo'q" deydi, "qaysi tur" ekanini emas. (Natija turini umuman yozmasangiz, TypeScript 5.5 dan beri bunday sodda tekshiruvda uni o'zi chiqaradi — keyingi darslarda.) Tuzatish: tur predikati — x is string (Custom type guard darsida).

9.4 Callback ichida xususiyat

if (obj.x) setTimeout(() => obj.x.trim()) — TS18048. Tuzatish: const x = obj.x va tekshiruv x ustida.

10. Mashqlar

1-mashq (oson): Bu joyda tur qanday?

ts
function pay(amount: number | string | null) {
  if (amount == null) return "summa yo'q";
  if (typeof amount === "string") return amount.trim();
  return amount.toFixed(0);
}
console.log(pay(null), pay(" 5000 ")); // summa yo'q 5000
console.log(pay(35000.4)); // 35000

Birinchi if ichida amount turi: [:null]. Ikkinchi if ichida: [:string]. Oxirgi return da: .

Yechim

amount == null — null (va undefined, lekin union'da u yo'q): if ichida null. Undan keyin string | number. typeof … === "string" — ichida string. Oxirida faqat number qoldi — "qolgani" qoidasi.

2-mashq (o'rta): in va instanceof bilan

To'lov ikki xil keladi: naqd ({ cash: number }) yoki karta ({ cardLast4: string }). Ba'zan esa Error (terminal ishlamadi). Funksiyani yozing: naqd — "Naqd: 50000", karta — "Karta: ****1234", xato — "Xato: <message>".

Ishora: avval instanceof Error (xato obyekti), keyin "cash" in payment.

Yechim
ts
type Cash = { cash: number };
type Card = { cardLast4: string };

function paymentText(payment: Cash | Card | Error): string {
  if (payment instanceof Error) {
    return `Xato: ${payment.message}`;
  }
  if ("cash" in payment) {
    return `Naqd: ${payment.cash}`;
  }
  return `Karta: ****${payment.cardLast4}`;
}

console.log(paymentText({ cash: 50000 })); // Naqd: 50000
console.log(paymentText({ cardLast4: "1234" })); // Karta: ****1234
const offline = new Error("terminal javob bermadi");
console.log(paymentText(offline)); // Xato: terminal javob bermadi

Tartib muhim: Error ham obyekt, in bilan avval tekshirsak, "cash" in payment Error uchun ham ishlab ketardi. instanceof bilan uni birinchi bo'lib ajratdik. Oxirgi return da payment — faqat Card.

3-mashq (qiyin): Amaliy tajriba — jadval kataklari

Mashq kurs/mashqlar/15/ da. Kunlik hisobot jadvalida katakchalarda turli qiymatlar bor: matn, son, ha/yo'q, sana yoki bo'sh. Sardorning birinchi varianti tsc dan xatosiz o'tadi:

ts
// 11-narrowing/cells.ts — jadval kataklari (birinchi variant)
export type Cell =
  | string
  | number
  | boolean
  | Date
  | null
  | undefined;

export function cellText(value: Cell): string {
  if (!value) {
    return "—";
  }
  if (typeof value === "number") {
    return value.toLocaleString("ru-RU");
  }
  if (typeof value === "object") {
    return value.toISOString().slice(0, 10);
  }
  return value ? "ha" : "yo'q";
}

Kerakli natijalar: null, undefined, "" — "—"; 0 — "0"; false — "yo'q", true — "ha"; "Osh" — "Osh"; 35000 — "35 000"; sana — "2026-10-06" ko'rinishida.

  1. 11-narrowing/cells.test.ts da shu natijalar uchun testlar yozing va birinchi variantda ishga tushiring. Qaysi testlar yiqiladi va nega tsc buni ko'rmadi?
  2. cellText ni qayta yozing: har tur uchun aniq tekshiruv, truthiness'siz. Oxirgi return da value — faqat Date bo'lsin (TypeScript o'zi chiqarsin).
  3. Dish (name, cookMinutes) va Drink (name, hot) turlari va waitText(item) ni qo'shing: taom — "Osh: 40 daqiqa", ichimlik — "Ko'k choy: darhol, issiq". Test ham yozing.
Yechim

1-qadam: birinchi variantda 3 ta testdan 2 tasi yiqildi (ℹ pass 1, ℹ fail 2). Xabarlar:

text
'—' !== '0'
'ha' !== 'Osh'

Ikki mantiq xatosi: if (!value) 0 va false ni ham "bo'sh" qildi; oxirgi qatordagi value — string | true, satrlar ham "ha" bo'lib chiqdi. tsc uchun hammasi to'g'ri: har joyda tur xavfsiz toraytirilgan. TypeScript turlarni tekshiradi, niyatni emas — testlar shuning uchun kerak.

ts
// 11-narrowing/cells.ts — hisobot jadvali kataklari
export type Cell =
  | string
  | number
  | boolean
  | Date
  | null
  | undefined;

export function cellText(value: Cell): string {
  // == null: null ham, undefined ham (ikkalasi bir tekshiruvda)
  if (value == null || value === "") {
    return "—";
  }
  if (typeof value === "string") {
    return value;
  }
  if (typeof value === "number") {
    return value.toLocaleString("ru-RU");
  }
  if (typeof value === "boolean") {
    return value ? "ha" : "yo'q";
  }
  // Qolgani — faqat Date: TS buni o'zi chiqardi
  return value.toISOString().slice(0, 10);
}

export type Dish = {
  readonly name: string;
  readonly cookMinutes: number;
};
export type Drink = { readonly name: string; readonly hot: boolean };

export function waitText(item: Dish | Drink): string {
  if ("cookMinutes" in item) {
    return `${item.name}: ${item.cookMinutes} daqiqa`;
  }
  return `${item.name}: darhol, ${item.hot ? "issiq" : "sovuq"}`;
}

Oxirgi return da Date ni tekshirmadik — null, undefined, string, number, boolean birma-bir chiqarib tashlandi. Agar ertaga Cell ga bigint qo'shilsa, value.toISOString() qatori TS2551 beradi ("bigint | Date da toISOString yo'q, toString ni nazarda tutdingizmi?"): "qolgani" endi bigint | Date. Turlar kelajakdagi o'zgarishni ham ushlaydi.

ts
// 11-narrowing/cells.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { cellText, waitText } from "./cells.ts";

test("cellText: bo'sh qiymatlar — chiziqcha", () => {
  assert.equal(cellText(null), "—");
  assert.equal(cellText(undefined), "—");
  assert.equal(cellText(""), "—");
});

test("cellText: 0 va false ham qiymat", () => {
  assert.equal(cellText(0), "0");
  assert.equal(cellText(false), "yo'q");
  assert.equal(cellText(true), "ha");
});

test("cellText: satr, son va sana", () => {
  assert.equal(cellText("Osh"), "Osh");
  assert.match(cellText(35000), /^35\s000$/);
  const day = new Date("2026-10-06T12:00:00Z");
  assert.equal(cellText(day), "2026-10-06");
});

test("waitText: taom va ichimlik", () => {
  const osh = { name: "Osh", cookMinutes: 40 };
  const tea = { name: "Ko'k choy", hot: true };
  assert.equal(waitText(osh), "Osh: 40 daqiqa");
  assert.equal(waitText(tea), "Ko'k choy: darhol, issiq");
});

npx tsc --pretty false — chiqishsiz. node --test 11-narrowing/cells.test.ts — bizda (Node 24.21.0):

text
✔ cellText: bo'sh qiymatlar — chiziqcha (2.7257ms)
✔ cellText: 0 va false ham qiymat (45.295ms)
✔ cellText: satr, son va sana (3.1228ms)
✔ waitText: taom va ichimlik (0.6345ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 388.7153

XATOLAR.md ga: TS18047 (typeof … "object" dagi null), callback ichidagi TS18048. Keyin kurs/mashqlar papkasidan:

bash
git add 15/11-narrowing 15/XATOLAR.md
git commit -m "15/11: cells.ts — typeof, in va == null"

11. Real ishda

  • Har kunlik kod — toraytirish TypeScript'da eng ko'p yoziladigan narsa: if (user === null) return;, if (error instanceof Error), if (typeof value === "string"). Ularning har biri keyingi qatorlardagi xatolarni oldini oladi.
  • "Erta qaytish" (early return) uslubi (return va erta qaytish) toraytirish bilan ayniqsa yaxshi ishlaydi: har return dan keyin tur torayib boradi, kod esa chapga "yopishib" turadi.
  • DOM: document.querySelector — Element | null. Har DOM kodi if (!el) return; bilan boshlanadi (TypeScript va DOM darsida — vazifalar dagi 106 ta possibly 'null' xatosi).
  • Intervyu: "Narrowing nima va qaysi usullar bor?", "Nega typeof x === 'object' dan keyin ham x null bo'lishi mumkin?" — tez-tez so'raladi.

Xulosa

  • TypeScript kod oqimini kuzatadi: har tekshiruvdan keyin union torayadi, oxirida "qolgani" o'zi chiqariladi.
  • Beshta usul: typeof (primitivlar), truthiness (if (x)), tenglik (=== null, == null, literal), in (obyekt xususiyati), instanceof (klasslar).
  • typeof null === "object" — TS18047. Sonlarda if (x) 0 ni ham "yo'q" qiladi — !== undefined yozing.
  • Toraytirish callback'da yo'qolishi mumkin (obyekt xususiyati, qayta yoziladigan let) — qiymatni const ga oling.
  • TypeScript turni tekshiradi, niyatni emas: mantiq xatolari uchun testlar kerak.

Keyingi dars: Discriminated union va to'liqlik tekshiruvi — umumiy kind maydoni bilan holatlarni xavfsiz modellashtiramiz va never bilan "hamma variant ko'rib chiqildi" ni tekshiramiz.

Manbalar

  • TypeScript Handbook: "Narrowing" — typescriptlang.org/docs/handbook/2/narrowing.html
  • TypeScript Release Notes 5.4 ("Preserved Narrowing in Closures Following Last Assignments") — typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html
  • MDN: typeof, in, instanceof — developer.mozilla.org/docs/Web/JavaScript/Reference/Operators
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript narrowing: turni toraytirish — typeof, in, instanceof va tekshiruvlar — IlmHamroh