Tarkibga o'tish

9 β€” any, unknown, never va void

⬅️ Oldingi: 08 β€” Type narrowing va type guard'lar Β· 🏠 README Β· Keyingi: 10 β€” Type alias, intersection va kompozitsiya ➑️

Bu bobda: TypeScript'ning to'rtta o'ziga xos "chekka" tipini o'rganamiz. any β€” tip tekshiruvini butunlay o'chiradigan xavfli "qochish yo'li"; unknown β€” uning xavfsiz aksi: qiymat noma'lum, lekin ishlatishdan oldin tekshirish (narrowing) majbur; never β€” hech qachon yuz bermaydigan, qiymati bo'lmagan tip (xato otkazuvchi va tugamaydigan funksiyalar, exhaustiveness qo'riqchisi); void β€” hech narsa qaytarmaydigan funksiya tipi. Eng muhimi β€” any bilan unknown orasidagi farqni, noImplicitAnyni va as assertion'ning xavfini ko'rib chiqamiz.


Muammo

Tasavvur qiling, serverdan JSON javob keldi va siz uni o'qiysiz. JavaScript'da bu odatiy ish edi:

const javob = await fetch("/api/mahsulot/1");
const data = await javob.json();
console.log(data.narx.toFixed(2));   // narxni 2 xonali ko'rsat

JavaScript'da bu kod runtime'gacha hech qanday ogohlantirmaydi. Agar API narxni "120ming" (matn) sifatida qaytarsa yoki narx umuman bo'lmasa, dastur foydalanuvchi oldida portlaydi: Cannot read properties of undefined yoki narx.toFixed is not a function.

TypeScript'ga o'tdik degani β€” bunday xatolar avtomatik yo'qoladi degani emas. javob.json() qanday tip qaytaradi, deb o'ylaysiz? Eng muhim savol shu. Agar u noma'lum tip qaytarsa, biz uni tekshirishga majbur bo'lamiz β€” bu yaxshi. Agar u har narsani ruxsat etadigan tip qaytarsa, biz xuddi JavaScript'dagidek xatoga yo'l qo'yamiz β€” bu yomon.

Aynan shu yerda any va unknown farqi hal qiluvchi bo'ladi. Bu bobda biz noma'lum yoki imkonsiz qiymatlarni TypeScript'da to'g'ri ifodalashni o'rganamiz. Boshqacha aytganda β€” kompilyatorni o'zimizga qarshi emas, o'zimiz tomonda ishlashga majbur qilamiz.


any β€” tip tekshiruvini o'chiradigan tugma

any (inglizcha "har qanday") β€” bu maxsus tip bo'lib, unga belgilangan qiymat ustida TypeScript hech qanday tekshiruv qilmaydi. any qiymat bilan istalgan narsani qilsangiz bo'ladi: istalgan metodni chaqirasiz, istalgan ustunga murojaat qilasiz, istalgan tipga uzatasiz β€” kompilyator jim turadi.

let x: any = "salom";

x.toUpperCase();        // OK
x.foo.bar.baz;          // OK (kompilyator tekshirmaydi!)
x();                    // OK (x ni funksiya deb chaqirdik)
const son: number = x;  // OK (any hammaga "beriladi")

Yuqoridagi kodning birorta qatori kompilyatsiyada xato bermaydi β€” lekin deyarli har biri runtime'da portlashi mumkin. any aslida "TypeScript, bu qiymatga aralashma" degani.

πŸ“Œ any β€” tip tizimidagi "qora teshik". U bilan ishlasangiz, TypeScript'ning butun foydasi β€” avtomatik tekshiruv β€” shu nuqtada yo'qoladi. Shuning uchun anyni "men nima qilayotganimni bilaman, javobgarlikni o'z bo'ynimga olaman" degan imzo deb tushuning.

any qachon kerak bo'ladi?

anyni butunlay yomon deb bo'lmaydi β€” ba'zan u vaqtinchalik kerak:

  • Migratsiyada: katta JavaScript loyihasini TypeScript'ga ko'chirayotganda, hamma narsani birdan tiplab bo'lmaydi. any β€” vaqtincha "keyin qaytaman" belgisi. (Bu mavzu 23-bobda batafsil.)
  • Juda murakkab uchinchi tomon kutubxonasi to'g'ri tip bermaganda, oxirgi chora sifatida.

Lekin yangi yozayotgan kodda any deyarli har doim xato tanlovdir. Ko'pincha uning o'rniga unknown yoki aniq tip yozish kerak.

πŸ’‘ Maslahat: anyni "to'g'rilash kerak" degan TODO deb belgilang. Ko'p jamoalar ESLint qoidasi (no-explicit-any) bilan kodda anyni umuman taqiqlaydi.

any "yuqadi" β€” eng yashirin xavf

anyning eng xavfli tomoni β€” u tarqaladi. any qiymatdan kelib chiqqan har qanday natija ham avtomatik any bo'ladi. Boshlang'ich muammomizga qaytaylik:

const data: any = JSON.parse('{"narx": "120ming"}');

const narx = data.narx;     // narx: any
const jami = narx * 2;      // jami: any  ("120ming" * 2 = NaN, lekin TS jim)
const yana = jami.toFixed(2); // yana: any

data any bo'lgani uchun data.narx ham any, narx * 2 ham any, va hokazo. Tip xavfsizligi butun zanjir bo'ylab "o'chib" boradi. narx aslida matn bo'lsa, narx * 2 β€” NaN, lekin kompilyator bironta ham xato bermaydi.

any yuqishi: bitta any qiymatdan kelib chiqqan har bir natija ham any bo'ladi, tip xavfsizligi zanjir bo'ylab yo'qoladi

πŸ“Œ Mana shuning uchun bitta e'tiborsiz any butun fayl bo'ylab "infektsiya" tarqatishi mumkin. Bitta funksiya any qaytarsa, uni chaqirgan har bir joy ham tekshiruvni yo'qotadi.

unknown β€” noma'lum, lekin XAVFSIZ

Endi eng muhim qahramon. unknown (inglizcha "noma'lum") β€” bu ham "tipi noma'lum" degan ma'noni beradi, lekin anydan farqli ravishda TypeScript uni tekshirishni majbur qiladi. unknown qiymat bilan to'g'ridan-to'g'ri hech narsa qila olmaysiz β€” avval uning aslida nima ekanini isbotlashingiz kerak.

let x: unknown = "salom";

// ❌ Xato: 'x' is of type 'unknown'.
x.toUpperCase();

Kompilyator: 'x' is of type 'unknown'. β€” ya'ni "x noma'lum tipga ega, men senga toUpperCase chaqirishga ruxsat bera olmayman, chunki x matn ekaniga ishonchim yo'q".

Yechim β€” narrowing (tipni toraytirish, 8-bobda o'rgangan edik). unknownni ishlatishdan oldin uni typeof, in, instanceof yoki type guard bilan tekshirib, aniq tipga "toraytirishingiz" shart:

function ishlat(qiymat: unknown): string {
  if (typeof qiymat === "string") {
    return qiymat.toUpperCase();   // bu yerda qiymat: string β€” OK
  }
  if (typeof qiymat === "number") {
    return qiymat.toFixed(2);      // bu yerda qiymat: number β€” OK
  }
  return "noma'lum tur";
}

ishlat("salom");   // "SALOM"
ishlat(3.14159);   // "3.14"
ishlat(true);      // "noma'lum tur"

Ko'rdingizmi? if (typeof qiymat === "string") bloki ichida TypeScript endi qiymatni string deb biladi va toUpperCase()ga ruxsat beradi. Tekshiruvsiz β€” yo'q. Aynan shu narsa unknownni anyning xavfsiz aksi qiladi.

any tekshiruvni o'chiradi, unknown esa ishlatishdan oldin narrowing majbur qiladi β€” yonma-yon taqqoslash

any vs unknown β€” eng muhim farq

Bu bobning eng muhim jadvali. Ikkalasi ham "tipi noma'lum" degani, lekin yondashuvlari teskari:

any unknown
Metod chaqirish (x.foo()) βœ… ruxsat (tekshirilmaydi) ❌ avval narrowing kerak
Boshqa tipga berish (const s: string = x) βœ… ruxsat (xavfli) ❌ avval narrowing kerak
Xato tutiladimi? ❌ yo'q βœ… ha
Xavfsizmi? ❌ yo'q βœ… ha
Qachon? migratsiya, oxirgi chora noma'lum tashqi ma'lumot

Oddiy qoida: noma'lum qiymat kirsa, any emas, unknown yozing. Shunda TypeScript sizni uni tekshirishga majbur qiladi va xatolarni ushlaydi.

// JSON.parse standart holatda 'any' qaytaradi β€” buni unknown'ga "ushlab" oling:
function xavfsizParse(matn: string): unknown {
  return JSON.parse(matn);
}

const natija = xavfsizParse('{"ism": "Ali"}');

// ❌ Xato: 'natija' is of type 'unknown'.
// console.log(natija.ism);

// βœ… Avval tekshirib, keyin ishlatamiz:
if (
  typeof natija === "object" &&
  natija !== null &&
  "ism" in natija &&
  typeof (natija as { ism: unknown }).ism === "string"
) {
  const obj = natija as { ism: string };
  console.log(obj.ism.toUpperCase());   // xavfsiz
}

πŸ’‘ unknownni shunchaki boshqa unknownga yoki anyga berish mumkin β€” chunki bu yangi xavf tug'dirmaydi. Lekin aniq tipga (string, number...) berish uchun har doim narrowing yoki assertion kerak.

Type guard funksiyalari unknown bilan

Tashqi ma'lumotni har safar qo'lda tekshirish zerikarli. Yaxshi yechim β€” bir marta type guard (8-bobdagi qiymat is Tur funksiyasi) yozib, uni qayta ishlatish:

interface Foydalanuvchi {
  ism: string;
  yosh: number;
}

function foydalanuvchimi(qiymat: unknown): qiymat is Foydalanuvchi {
  return (
    typeof qiymat === "object" &&
    qiymat !== null &&
    "ism" in qiymat &&
    "yosh" in qiymat &&
    typeof (qiymat as Record<string, unknown>).ism === "string" &&
    typeof (qiymat as Record<string, unknown>).yosh === "number"
  );
}

function ishlat(data: unknown): void {
  if (foydalanuvchimi(data)) {
    console.log(data.ism, data.yosh);   // data: Foydalanuvchi
  } else {
    console.log("Noto'g'ri format");
  }
}

ishlat({ ism: "Lola", yosh: 25 });   // Lola 25
ishlat("xato");                      // Noto'g'ri format

Bu β€” real loyihalarda API javoblarini, localStoragedan kelgan ma'lumotni va JSON.parse natijasini xavfsiz ishlash uchun eng to'g'ri qolip: tashqaridan kelganni unknown deb qabul qilib, type guard orqali ishonchli tipga aylantirish.

πŸ“Œ Eslatma: Record<string, unknown> β€” bu "kalitlari string, qiymatlari noma'lum bo'lgan obyekt" degani. Type guard ichida vaqtincha as Record<string, unknown> qilish β€” obyekt ekani allaqachon tekshirilgandan keyin uning ustunlariga murojaat qilishning xavfsiz usuli.

never β€” hech qachon bo'lmaydigan qiymat

never β€” TypeScript'dagi eng g'alati, lekin eng aqlli tip. U "qiymati bo'lishi mumkin emas bo'lgan tip" degani. stringda matnlar, numberda sonlar bor; neverda esa hech qanday qiymat yo'q.

Bu birinchi qarashda foydasizdek tuyuladi, lekin u uchta muhim joyda paydo bo'ladi.

never qayerda paydo bo'ladi: xato otkazuvchi funksiya, cheksiz sikl va exhaustiveness tekshiruvi

1. Xato otkazadigan funksiya

Hech qachon normal return qilmaydigan, doim xato otkazadigan funksiyaning qaytish tipi never bo'ladi:

function xatoOtkaz(xabar: string): never {
  throw new Error(xabar);
}

Bu funksiya hech qachon qiymat qaytarib bera olmaydi β€” chunki throwgacha yetib boradi-yu, undan keyin kod yo'q. Shuning uchun never. Bunday yordamchi funksiya juda foydali:

function olish(qiymat: number | undefined): number {
  if (qiymat === undefined) {
    xatoOtkaz("Qiymat yo'q");   // bu yo'ldan keyin oqim tugaydi
  }
  return qiymat;   // bu yerda qiymat: number (undefined imkoni yo'q)
}

TypeScript xatoOtkaz never qaytarishini biladi, shuning uchun ifdan keyin qiymat faqat number bo'lishi mumkinligini tushunadi. return undefined xavfi yo'qoladi.

2. Hech qachon tugamaydigan funksiya

Cheksiz sikl ham hech qachon qiymat qaytarmaydi:

function abadiyKut(): never {
  while (true) {
    // hech qachon return qilmaydi
  }
}

πŸ“Œ never va void farqini chalkashtirmang: void qaytaruvchi funksiya tugaydi, lekin qiymat qaytarmaydi (return;gacha yetadi). never qaytaruvchi funksiya esa umuman tugamaydi yoki xato otkazadi β€” oxirigacha yetib bormaydi.

3. Exhaustiveness β€” union'ni "to'liq qoplaganini" tekshirish

Bu neverning eng kuchli amaliy qo'llanilishi. Union tip (7-bob) bilan ishlaganda, har bir holatni qoplaganingizni TypeScript bilan kafolatlash mumkin:

type Holat = "kutilmoqda" | "bajarildi" | "bekor";

function holatMatni(h: Holat): string {
  switch (h) {
    case "kutilmoqda":
      return "Kutilmoqda...";
    case "bajarildi":
      return "Bajarildi";
    case "bekor":
      return "Bekor qilindi";
    default: {
      const tekshir: never = h;   // hamma case qoplangach, h β€” never
      return tekshir;
    }
  }
}

Mantiq: barcha mumkin bo'lgan holatlarni caselar bilan "yeb" bo'lgach, defaultga faqat mumkin bo'lmagan qiymat kelishi mumkin. Bunday qiymat yo'q, shuning uchun hning tipi neverga "toraygan" bo'ladi va const tekshir: never = h toza o'tadi.

Endi sehrli qism. Faraz qilaylik, kelajakda Holatga yangi a'zo qo'shasiz:

type Holat = "kutilmoqda" | "bajarildi" | "bekor" | "kutilyapti";

Lekin holatMatniga yangi case qo'shishni unutdingiz. Endi default blokida h "kutilyapti" bo'lishi mumkin β€” u never emas:

    default: {
      // ❌ Xato: Type '"kutilyapti"' is not assignable to type 'never'.
      const tekshir: never = h;
      return tekshir;
    }

TypeScript sizni kompilyatsiya vaqtida ogohlantiradi: "yangi holatni unutding!". Bu β€” runtime'da yashirin bug o'rniga, hali kod yozayotganda ushlanadigan xato. Mana shuning uchun never β€” eng yaxshi tuzoq qo'riqchisi.

πŸ’‘ Ko'pincha bu qolipni alohida yordamchi funksiyaga ajratadilar β€” kodingiz toza va qayta ishlatiladigan bo'ladi:

function imkonsizHolat(qiymat: never): never {
  throw new Error("Kutilmagan holat: " + JSON.stringify(qiymat));
}

type Shakl =
  | { tur: "doira"; radius: number }
  | { tur: "kvadrat"; tomon: number };

function yuza(s: Shakl): number {
  switch (s.tur) {
    case "doira":
      return Math.PI * s.radius ** 2;
    case "kvadrat":
      return s.tomon ** 2;
    default:
      return imkonsizHolat(s);   // yangi shakl qo'shilsa, shu yerda xato chiqadi
  }
}

πŸ“Œ Yana bir xususiyat: never har qanday tipga "beriladi" (chunki u hech qachon yuz bermaydi, qarama-qarshilik yo'q), lekin hech narsa (faqat neverning o'zidan boshqa) neverga berilmaydi. Shuning uchun imkonsizHolat(s) natijasini number qaytaradigan funksiyada return qilsa bo'laveradi.

void β€” hech narsa qaytarmaydigan funksiya

void β€” eng oddiy maxsus tip. U funksiya qiymat qaytarmasligini bildiradi:

function logla(xabar: string): void {
  console.log("[LOG]", xabar);
  // return yo'q (yoki bo'sh "return;")
}

JavaScript'da returnsiz funksiya aslida undefined qaytaradi, lekin void "bu qaytgan qiymatdan foydalanmang, u ahamiyatsiz" degan niyatni bildiradi. Farqi nozik, lekin muhim.

πŸ“Œ void bilan undefined bir xil emas. void β€” "qiymat qaytarmaydi, qaytsa ham e'tiborga olinmaydi"; undefined β€” aniq bitta qiymat (undefinedning o'zi). Odatda funksiya qaytish tipi sifatida void ishlatiladi.

voidning eng foydali joyi β€” callback tiplarida. void qaytaradigan callback'da TypeScript "qiymat qaytsa ham, men uni e'tiborga olmayman" deydi:

const sonlar: number[] = [];
[1, 2, 3].forEach((n) => sonlar.push(n));

Bu yerda sonlar.push(n) aslida number (massiv yangi uzunligi) qaytaradi, lekin forEachning callback'i void kutadi β€” shuning uchun TypeScript qaytgan sonni e'tiborga olmaydi va xato bermaydi. Bu "qulay yengillik" voidning maxsus qoidasi:

type Tugma = {
  bosilganda: () => void;
};

const tugma: Tugma = {
  bosilganda: () => 42,   // OK: void kutilgani uchun, 42 e'tiborga olinmaydi
};

πŸ’‘ Agar callback haqiqatan ham qiymat qaytarsin desangiz, () => void o'rniga aniq tip yozing, masalan () => number. void β€” "natijasi keraksiz" degani.

Type assertion (as) va uning xavfi

Ba'zan siz qiymatning tipini kompilyatordan yaxshiroq bilasiz. as operatori β€” "ishon menga, bu qiymat aslida shu tipda" deyishning usuli (buni type assertion β€” tip da'vosi deymiz):

const element = document.getElementById("input") as HTMLInputElement;
console.log(element.value);   // .value faqat input'da bor

Bu yerda getElementById HTMLElement | null qaytaradi, lekin biz bu aniq <input> ekanini bilamiz, shuning uchun as bilan toraytiramiz. (DOM mavzusi 19-bobda batafsil.)

Lekin as β€” xavfli quroldir. U hech qanday tekshiruv qilmaydi, shunchaki kompilyatorga "ishonadi". Agar yolg'on da'vo qilsangiz, runtime'da portlaysiz:

const malumot: unknown = "men matnman";

// ❌ Mantiqiy xato: aslida string, lekin number deb da'vo qilyapmiz
const son = malumot as number;
console.log(son.toFixed(2));   // runtime: son.toFixed is not a function

Bu kod kompilyatsiyadan o'tadi β€” TypeScript asga ishondi. Lekin runtime'da "men matnman".toFixed mavjud emas, dastur portlaydi. as β€” TypeScript'ga "ko'zingni yum" deyishning usuli; mas'uliyat to'liq sizda.

as unknown as β€” ikki bosqichli "majburlash"

TypeScript bir-biriga umuman o'xshamagan tiplarni to'g'ridan-to'g'ri as qilishga ham yo'l qo'ymaydi:

const matn = "salom";

// ❌ Xato: Conversion of type 'string' to type 'number' may be a mistake
//    because neither type sufficiently overlaps with the other.
const son = matn as number;

Kompilyator: "string'ni number'ga aylantirish xato bo'lishi mumkin, ular yetarlicha o'xshamaydi". Lekin xato xabarining o'zi yo'lni ko'rsatadi: agar chindan ham shuni xohlasangiz, avval unknownga o'tkazing. Mana shu as unknown as qolipi:

const yana = "matn" as unknown as number;   // kompilyator endi qarshilik qilmaydi

πŸ“Œ as unknown as X β€” TypeScript'da eng xavfli ifoda. U "men kompilyatorni ikki marta aldayapman" degani. Agar shuni yozayotgan bo'lsangiz, deyarli har doim dizayningizda xato bor. Real loyihada bu juda kam, faqat juda nozik holatlarda (masalan, eski kutubxona tiplari noto'g'ri bo'lganda) qo'llaniladi.

πŸ’‘ Qoida: assertion (as) β€” narrowing'ning o'rnini bosa olmaydi. Iloji bo'lsa, as o'rniga if (typeof ...) yoki type guard bilan haqiqiy tekshirish yozing. as faqat siz haqiqatan ham kompilyatordan ko'proq bilganda (masalan DOM elementi tipi) ishlatiladi.

noImplicitAny β€” yashirin anyga qarshi

strict rejimda (tsconfig.jsonda "strict": true) noImplicitAny opsiyasi yoqilgan bo'ladi. U yashirin anyni β€” ya'ni siz yozmagan, lekin TypeScript "topa olmagani uchun" qo'ygan anyni β€” taqiqlaydi:

function salomla(ism) {
  // ❌ Xato: Parameter 'ism' implicitly has an 'any' type.
  return "Salom, " + ism;
}

ismga tip yozmaganingiz uchun TypeScript uni any deb belgilamoqchi bo'ldi, lekin noImplicitAny bunga yo'l qo'ymaydi. Yechim β€” tipni aniq yozish:

function salomla(ism: string): string {
  return "Salom, " + ism;
}

πŸ“Œ noImplicitAny β€” strictning eng foydali qismlaridan biri. U sizni har bir parametr va o'zgaruvchiga tip berishga "majburlaydi" β€” natijada TypeScript butun kuchini ko'rsatadi. Agar aniq any xohlasangiz (ism: any), TypeScript qarshilik qilmaydi β€” chunki bu sizning ongli tanlovingiz. Taqiqlanadigani β€” yashirin, e'tiborsizlikdan kelib chiqqan any.

πŸ’‘ Yangi loyihada doim "strict": true bilan boshlang. noImplicitAnyni o'chirish β€” TypeScript'ning yarmidan voz kechish bilan teng. (tsconfig'ning barcha opsiyalari 18-bobda.)

Hammasini bir joyda β€” qaysi birini qachon?

Tip Ma'nosi Qachon ishlatiladi
any tekshiruv o'chiq, har narsa ruxsat deyarli hech qachon (migratsiya, oxirgi chora)
unknown noma'lum, lekin tekshirish majbur tashqaridan kelgan ma'lumot (API, JSON, localStorage)
never qiymat bo'lishi mumkin emas xato otkazuvchi funksiya, exhaustiveness qo'riqchisi
void qiymat qaytarmaydi hech narsa qaytarmaydigan funksiya/callback

Asosiy xulosalar:

  • anydan qoching. U tip xavfsizligini o'chiradi va "yuqadi". Yangi kodda any ko'rsangiz, "bu yerda nimadir noto'g'ri" deb o'ylang.
  • unknown β€” to'g'ri tanlov noma'lum ma'lumot uchun. U sizni narrowing bilan tekshirishga majbur qiladi β€” bu aynan kerakli xavfsizlik.
  • never β€” bug oldini oluvchi qurol. Uni exhaustiveness uchun ishlatib, kelajakdagi union o'zgarishlaridan himoyalaning.
  • void β€” oddiygina "qaytgan qiymat keraksiz" degani.
  • asni ehtiyot bo'lib ishlating: u tekshirmaydi, faqat ishonadi. as unknown as esa "qizil bayroq" β€” deyarli har doim dizaynni qayta ko'rib chiqish kerakligini bildiradi.

9-bob mashqlari

πŸ’‘ Mashqlarni alohida .ts faylda yozib, tsc --noEmit --strict bilan tekshiring. "❌ xato chiqishi kerak" deganlarda β€” xato chindan chiqishini ko'ring; "βœ… toza o'tsin" deganlarda β€” kompilyatsiya xatosiz o'tishini kuzating.

  1. let x: any = 5; deb e'lon qiling, so'ng x.toFixed(), x.foo.bar va x() yozing β€” uchalasi ham kompilyatsiyadan o'tishini va birortasi xato bermasligini ko'ring (any tekshiruvni o'chiradi).

  2. Yuqoridagi xni unknownga o'zgartiring. Endi qaysi qatorlar ❌ xato berishini va xato matni nima ekanini yozib qo'ying.

  3. unknown tipdagi parametr qabul qiluvchi chiqar(qiymat: unknown) funksiyasi yozing. typeof bilan narrowing qilib: string bo'lsa katta harfda, number bo'lsa 2 xonali kasrda, boshqa holatda "noma'lum" qaytaring. βœ… Toza o'tsin.

  4. JSON.parse('{"a": 1}') natijasini unknown tipga ushlab oling. To'g'ridan-to'g'ri .aga murojaat qilib ❌ xatoni ko'ring, so'ng narrowing bilan tekshirib xavfsiz murojaat qiling.

  5. Bir xil mantiqni avval any bilan, keyin unknown bilan yozing: data.narx * 2. any versiyada xato chiqmasligini, unknown versiyada chiqishini taqqoslang.

  6. xatoOtkaz(xabar: string): never funksiyasi yozing β€” throw new Error(xabar). Qaytish tipini never qilib belgilang va βœ… toza o'tishini ko'ring.

  7. 6-mashqdagi funksiyadan foydalanib, topshiriqOl(id: number | null): number yozing: id null bo'lsa xatoOtkaz chaqiring, aks holda idni qaytaring. return qatorida idning numberga "toraygani"ni kuzating.

  8. never qaytaruvchi cheksiz sikl funksiyasi (while (true) {}) yozing va uning qaytish tipi never bo'lishini tekshiring.

  9. type Yonalish = "shimol" | "janub" | "sharq" | "garb" union'ini yozing. switch bilan har biriga matn qaytaring va defaultda const tekshir: never = y qo'yib exhaustiveness tekshiruvini qo'shing. βœ… Toza o'tsin.

  10. 9-mashqdagi Yonalishga "shimoli-sharq" a'zosini qo'shing, lekin switchga yangi case qo'shmang. defaultda ❌ xato chiqishini va xato matnini yozib qo'ying.

  11. imkonsizHolat(qiymat: never): never yordamchi funksiyasini yozing (throw bilan). Uni 9-mashqdagi switchning defaultida return imkonsizHolat(y) ko'rinishida ishlating.

  12. void qaytaruvchi xabarChiqar(matn: string): void funksiyasi yozing. Funksiya ichida return; yozib ko'ring (qiymatsiz) β€” toza o'tishini, return matn; yozsangiz ❌ xato berishini taqqoslang.

  13. type Hodisa = { bosilganda: () => void } tipini yozing va bosilgandaga () => 42 beradigan obyekt yarating. βœ… Toza o'tishini (void callback qaytgan qiymatni e'tiborga olmasligini) ko'ring.

  14. const x: unknown = "salom"; const s: string = x; yozing va ❌ xatoni ko'ring. So'ng narrowing yoki as bilan to'g'rilang.

  15. as assertion bilan: const son = ("matn" as unknown) as number; yozing. Kompilyatsiyadan o'tishini, lekin son.toFixed(2) runtime'da xato berishini izohda yozib qo'ying (haqiqatan ishga tushiring).

  16. To'g'ridan-to'g'ri "matn" as number yozib ❌ kompilyatsiya xatosini ko'ring. Xato matni qaysi yo'lni (as unknown as) taklif qilishini yozib qo'ying.

  17. noImplicitAnyni sinash: tipsiz parametrli function qosh(a, b) { return a + b; } yozing va --strict bilan ❌ xato chiqishini ko'ring. So'ng tiplarni qo'shib to'g'rilang.

  18. Type guard funksiyasi yozing: mahsulotmi(x: unknown): x is { nomi: string; narx: number }. Ichida typeof, in va !== null tekshiruvlarini birlashtiring. βœ… Toza o'tsin.

  19. 18-mashqdagi guard'dan foydalanib, unknown qabul qiluvchi funksiyada if (mahsulotmi(x)) ichida x.nomi va x.narxga xavfsiz murojaat qiling. Guard'siz murojaat ❌ xato berishini ham ko'ring.

  20. Yaxlit mashq: unknown qabul qiluvchi xavfsizSonOl(x: unknown): number funksiyasi yozing. x number bo'lsa o'zini qaytaring; string bo'lib Number(x) NaN bo'lmasa, sonni qaytaring; boshqa hamma holatda imkonsizHolat o'rniga throw bilan xato bering. any ishlatmang, faqat unknown + narrowing. βœ… Toza o'tsin.