7-bo‘lim

Tur qisqartirish

typeof, in, instanceof, tur predikatlari, tasdiqlash funksiyalari va tur tizimidagi uchta teshik.

🕑 29 daqiqa o‘qish 📄 904 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. typeof qorovuli
  2. typeof ning tuzog'i
  3. Rostlik bo'yicha toraytirish
  4. Tenglik ikkala tomonni toraytiradi
  5. in, instanceof, Array.isArray
  6. E'lon paytidagi toraytirish
  7. Tur predikatlari
  8. Tasdiqlash funksiyalari
  9. Birinchi teshik: predikat - va'da, isbot emas
  10. Ikkinchi teshik: o'zgartirishdan keyin ham toraytirish saqlanadi
  11. Uchinchi teshik: ! - tekshirilmaydigan va'da
  12. Toraytirish qayta chaqiruv ichida yo'qoladi
  13. Qayta tayinlash toraytirishni bekor qiladi
  14. Xulosa

6-bobda union yaratdik. Endi u bilan ishlash kerak: union ustida faqat umumiy amallar bor, qolganini ochish uchun turni toraytirish lozim.

TypeScript kod oqimini kuzatib, har bir nuqtada qiymatning turi nima ekanini hisoblab boradi. Bu oqim tahlili (control flow analysis) deyiladi.

Bobning oxirida esa bu tahlilning uchta teshigini ko'ramiz - tsc jim turgan holda dastur yiqiladigan uchta joy.

typeof qorovuli #

TS
function tekshir(x: string | number | boolean | undefined): string {
  if (typeof x === "string") return "satr: " + x.toUpperCase();
  if (typeof x === "number") return "son: " + x.toFixed(1);
  if (typeof x === "boolean") return "mantiqiy: " + String(x);
  return "aniqlanmagan";
}

console.log(tekshir("olma"));
console.log(tekshir(12.345));
console.log(tekshir(true));
console.log(tekshir(undefined));
Terminal
tsx src/typeof.ts
Natija
satr: OLMA
son: 12.3
mantiqiy: true
aniqlanmagan

Oxirgi return ga yetganda x ning turi undefined bo'lib qolgan - qolgan uchtasi allaqachon chiqib ketgan.

typeof ning tuzog'i #

TS
const qiymatlar: unknown[] = [null, {}, [], "salom", undefined];
for (const q of qiymatlar) console.log(typeof q);
Terminal
tsx src/nul.ts
Natija
object
object
object
string
undefined

typeof null - "object". Bu JavaScript ning 1995 yildagi xatosi va u hech qachon tuzatilmaydi. TypeScript ham shuni hisobga oladi:

TS
function nechta(x: string[] | null): number {
  if (typeof x === "object") {
    return x.length;
  }
  return 0;
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/nul2.ts(3,12): error TS18047: 'x' is possibly 'null'.

typeof x === "object" null ni chiqarib tashlamadi. To'g'ri tekshiruv - x !== null.

typeof natijasiNimani ajratadi
"string"Satr
"number"Son (NaN ham)
"boolean"Mantiqiy
"undefined"undefined
"function"Funksiya
"object"Obyekt, massiv va null

Rostlik bo'yicha toraytirish #

TS
function uzunlik(s: string | null | undefined): number {
  if (s) return s.length;
  return 0;
}

console.log(uzunlik("Olma"), uzunlik(null), uzunlik(undefined));
Terminal
tsx src/rost.ts
Natija
4 0 0

Bitta if (s) ham null ni, ham undefined ni chiqarib tashladi. Qisqa va qulay - lekin tuzog'i bor:

TS
function chop(n: number | undefined): string {
  if (!n) return "berilmagan";
  return `qiymat: ${n}`;
}

console.log(chop(12000));
console.log(chop(undefined));
console.log(chop(0));
Terminal
tsx src/rost2.ts
Natija
qiymat: 12000
berilmagan
berilmagan

0 haqiqiy qiymat edi, lekin "berilmagan" deb hisoblandi. tsc bu yerda hech qanday xato bermaydi - mantiq to'g'ri, niyat noto'g'ri.

TS
function chop(n: number | undefined): string {
  if (n === undefined) return "berilmagan";
  return `qiymat: ${n}`;
}

console.log(chop(12000));
console.log(chop(undefined));
console.log(chop(0));
Terminal
tsx src/rost3.ts
Natija
qiymat: 12000
berilmagan
qiymat: 0
Yolg'on qiymatlar ro'yxati

if (x) quyidagilarning hammasini rad etadi:

QiymatTuri
falseboolean
0, -0, 0nnumber, bigint
""string
null, undefined-
NaNnumber

Son yoki satr bilan ishlayotgan bo'lsangiz, === undefined yoki == null yozing. == null ikkalasini ham (null va undefined) tutadi - bu yagona foydali == ishlatilishi.

Tenglik ikkala tomonni toraytiradi #

TS
function solishtir(a: string | number, b: string | boolean): void {
  if (a === b) {
    console.log(a.toUpperCase(), b.toUpperCase());
  }
}

solishtir("Olma", "Olma");
Terminal
tsx src/teng.ts
Natija
OLMA OLMA

a === b rost bo'lsa, ikkalasi ham umumiy qismda - ya'ni string. TypeScript buni o'zi hisoblab chiqardi.

in, instanceof, Array.isArray #

TS
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; raqam: string };

function chop(t: Naqd | Karta): string {
  if ("raqam" in t) return "karta " + t.raqam;
  return "naqd " + t.miqdor;
}

console.log(chop({ usul: "karta", raqam: "8600" }));
console.log(chop({ usul: "naqd", miqdor: 12000 }));
Terminal
tsx src/ichida.ts
Natija
karta 8600
naqd 12000
TS
function sana(x: Date | string): string {
  if (x instanceof Date) return x.toISOString().slice(0, 10);
  return x;
}

function nechta(x: string | string[]): number {
  if (Array.isArray(x)) return x.length;
  return 1;
}

console.log(sana(new Date("2026-01-15")));
console.log(sana("2026-02-20"));
console.log(nechta("Olma"), nechta(["Olma", "Anor"]));
Terminal
tsx src/instans.ts
Natija
2026-01-15
2026-02-20
1 2

instanceof faqat sinflar bilan ishlaydi. Array.isArray - massivni aniqlashning yagona ishonchli yo'li, chunki typeof [] - "object".

E'lon paytidagi toraytirish #

Bu joyda oson adashish mumkin:

TS
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; raqam: string };
type Tolov = Naqd | Karta;

const t: Tolov = { usul: "karta", raqam: "8600" };
console.log(t.raqam);

function chop(x: Tolov): void {
  console.log(x.raqam);
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/elon.ts(9,17): error TS2339: Property 'raqam' does not exist on type
'Tolov'.
  Property 'raqam' does not exist on type 'Naqd'.

6-qatorda xato yo'q: t ga aniq qiymat berilgan, TypeScript uni Karta deb toraytirib qo'ygan. 9-qatorda esa x - funksiya parametri, uning qiymati noma'lum.

Shuning uchun toraytirish bilan tajriba qilayotganda funksiya parametrida sinang - o'zgaruvchi e'loni sizni chalg'itadi.

Tur predikatlari #

Tekshiruvni alohida funksiyaga chiqarsak, toraytirish yo'qoladi:

TS
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; raqam: string };
type Tolov = Naqd | Karta;

function kartami(t: Tolov): boolean {
  return t.usul === "karta";
}

function chop(t: Tolov): void {
  if (kartami(t)) console.log(t.raqam);
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/pred1.ts(10,33): error TS2339: Property 'raqam' does not exist on
type 'Tolov'.
  Property 'raqam' does not exist on type 'Naqd'.

boolean - shunchaki "rost yoki yolg'on", u nima haqida ekanini aytmaydi. Yechim - qaytish turini t is Karta qilish:

TS
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; raqam: string };
type Tolov = Naqd | Karta;

function kartami(t: Tolov): t is Karta {
  return t.usul === "karta";
}

function chop(t: Tolov): void {
  if (kartami(t)) console.log("karta " + t.raqam);
  else console.log("naqd " + t.miqdor);
}

chop({ usul: "karta", raqam: "8600" });
chop({ usul: "naqd", miqdor: 12000 });
Terminal
tsx src/pred2.ts
Natija
karta 8600
naqd 12000

else shoxida ham ishladi: Karta emas bo'lsa, Naqd.

Tasdiqlash funksiyalari #

if emas, "bo'lmasa, to'xta" degan variant ham bor:

TS
function satrBolishiKerak(x: unknown): asserts x is string {
  if (typeof x !== "string") throw new Error("satr emas");
}

const q: unknown = "Olma";
satrBolishiKerak(q);
console.log(q.toUpperCase());
Terminal
tsx src/asserts.ts
Natija
OLMA

Chaqiruvdan keyingi barcha qatorlarda q - string. Hech qanday if kerak emas, chunki funksiya qaytgan bo'lsa, demak xato tashlanmagan.

Birinchi teshik: predikat - va'da, isbot emas #

TypeScript t is Karta yozganingizga ishonadi. Funksiya ichini tekshirmaydi:

TS
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; raqam: string };
type Tolov = Naqd | Karta;

function kartami(t: Tolov): t is Karta {
  return true;
}

function chop(t: Tolov): void {
  if (kartami(t)) console.log(t.raqam.length);
}

chop({ usul: "naqd", miqdor: 12000 });
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/pred3.ts 2>&1 | grep -oE "TypeError.*" | head -1
Natija
tsc: xato yo_q
TypeError: Cannot read properties of undefined (reading 'length')

return true - ochiq yolg'on, lekin kompilyator uni o'tkazdi.

Ikkinchi teshik: o'zgartirishdan keyin ham toraytirish saqlanadi #

TS
type Mahsulot = { tavsif?: string };

const m: Mahsulot = { tavsif: "shirin" };

function tozala(): void {
  delete m.tavsif;
}

if (m.tavsif) {
  tozala();
  console.log(m.tavsif.length);
}
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/nosogl.ts 2>&1 | grep -oE "TypeError.*" | head -1
Natija
tsc: xato yo_q
TypeError: Cannot read properties of undefined (reading 'length')

if ichida m.tavsif - string. tozala() uni o'chirdi, lekin TypeScript chaqirilgan funksiya nima qilishini kuzatmaydi va toraytirishni bekor qilmaydi.

Uchinchi teshik: ! - tekshirilmaydigan va'da #

TS
function narxi(nomi: string): number | null {
  return nomi === "Olma" ? 12000 : null;
}

console.log(narxi("Olma")!.toFixed(0));
console.log(narxi("Anor")!.toFixed(0));
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/undov.ts 2>&1 | grep -oE "(^12000|TypeError.*)" | head -2
Natija
tsc: xato yo_q
12000
TypeError: Cannot read properties of null (reading 'toFixed')

! - "ishon, bu null emas" degani. Birinchisi to'g'ri edi, ikkinchisi yolg'on.

tsc jim turadigan uchta joy 1. Tur predikati function kartami(t): t is Karta { return true; } Ichi tekshirilmaydi Himoya: predikat tanasini qisqa va bir joyda saqlang yoki tashqi kutubxona bilan tekshiring 2. Keyingi o'zgarish if (m.tavsif) { tozala(); m.tavsif.length Chaqiruv kuzatilmaydi Himoya: qiymatni mahalliy const ga oling readonly maydon ishlating 3. Undov belgisi narxi("Anor")!.toFixed(0) natija: null Hech nima tekshirilmaydi Himoya: ?. yoki ?? ishlating ! ni kod tahlilida taqiqlang Umumiy qoida TypeScript siz aytgan narsaga ishonadi. Uchala teshik ham - dasturchi bergan va'da. Va'da qancha kam bo'lsa, tur tizimi shuncha ko'p foyda keltiradi.
Oqim tahlilining uchta chegarasi va ulardan himoya

Toraytirish qayta chaqiruv ichida yo'qoladi #

TS
type Mahsulot = { nomi: string; tavsif?: string };

function chop(m: Mahsulot): void {
  if (m.tavsif) {
    [1].forEach(() => {
      console.log(m.tavsif.length);
    });
  }
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/yopiq.ts(6,19): error TS18048: 'm.tavsif' is possibly 'undefined'.

Bu safar TypeScript ehtiyotkor: strelkali funksiya keyinroq ham ishlashi mumkin, u paytda m.tavsif allaqachon o'chirilgan bo'lishi mumkin.

Yechim - qiymatni mahalliy const ga olish:

TS
type Mahsulot = { nomi: string; tavsif?: string };

function chop(m: Mahsulot): void {
  const tavsif = m.tavsif;
  if (tavsif) {
    [1].forEach(() => console.log(m.nomi, tavsif.length));
  } else {
    console.log(m.nomi, "tavsifsiz");
  }
}

chop({ nomi: "Olma", tavsif: "shirin" });
chop({ nomi: "Anor" });
Terminal
tsx src/yopiq2.ts
Natija
Olma 6
Anor tavsifsiz

const tavsif hech qachon o'zgarmaydi, shuning uchun toraytirish kafolatli.

Nega bir joyda ehtiyotkor, boshqasida yo'q?
HolatTypeScriptSabab
Callback ichida maydonXato beradiKeyinroq ishlashi mumkin
Funksiya chaqiruvidan keyinJimHar chaqiruvni kuzatish juda qimmat

Ikkinchisi - ataylab qilingan murosa. Uni to'g'ri qilish uchun kompilyator har bir funksiya nimani o'zgartirishini bilishi kerak bo'lardi.

Shuning uchun const ga olish - eng ishonchli odat.

Qayta tayinlash toraytirishni bekor qiladi #

TS
let x: string | number = "Olma";

if (typeof x === "string") {
  x = 12000;
  console.log(x.toUpperCase());
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/qayta.ts(5,17): error TS2339: Property 'toUpperCase' does not exist
on type 'number'.

if ichida bo'lsa ham, x = 12000 dan keyin x - number. Oqim tahlili qatorma-qator ishlaydi.

Xulosa #

  • Toraytirish - union ichidan aniq turni ajratib olish; TypeScript buni oqim tahlili bilan qiladi.
  • typeof asosiy qorovul, lekin typeof null === "object" - null ni u ajratmaydi.
  • if (x) bitta tekshiruvda null va undefined ni rad etadi, lekin 0 va "" ni ham qo'shib rad etadi.
  • Son va satr bilan ishlaganda === undefined yoki == null yozing - bu == ning yagona foydali ishlatilishi.
  • a === b ikkala tomonni bir vaqtda toraytiradi.
  • in, instanceof va Array.isArray - qolgan uchta qorovul; massivni faqat Array.isArray ishonchli aniqlaydi.
  • E'lon paytida berilgan aniq qiymat o'zgaruvchini darhol toraytiradi - tajribani funksiya parametrida o'tkazing.
  • boolean qaytaruvchi tekshiruv toraytirmaydi; t is Karta qaytaruvchi tur predikati toraytiradi.
  • asserts x is T - chaqiruvdan keyingi barcha qatorlarga ta'sir qiladi.
  • Uchta teshik: predikat tanasi tekshirilmaydi, funksiya chaqiruvidan keyin toraytirish saqlanadi, ! hech narsani tekshirmaydi.
  • Callback ichida maydon toraytirishi yo'qoladi - qiymatni mahalliy const ga oling.
  • Qayta tayinlash toraytirishni bekor qiladi.
Amaliy topshiriq
  1. Uch a'zoli union uchun typeof bilan uchta shoxli funksiya yozing.
  2. typeof x === "object" bilan null ni ajratishga urinib, TS18047 ni oling.
  3. if (!n) ichiga 0 berib, noto'g'ri natijani ko'ring.
  4. Uni === undefined ga almashtirib tuzating.
  5. "maydon" in t bilan ikkita obyekt turini ajrating.
  6. Date | string uchun instanceof qorovulini yozing.
  7. boolean qaytaruvchi tekshiruv funksiyasini yozing va toraytirish yo'qolishini ko'ring.
  8. Uni t is Karta ga o'zgartirib, ishlaydigan qiling.
  9. return true yozib, predikatni yolg'onchi qiling va dasturni ish vaqtida yiqiting.
  10. Callback ichida ixtiyoriy maydonni ishlatib TS18048 ni oling, keyin const ga olib tuzating.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.