IlmHamroh
JavaScript Full-stack/15-qism. TypeScript15/47-dars17 daqiqa
Mundarija (28)

TypeScript'da null va undefined bilan xavfsiz ishlash: strictNullChecks

Qisqacha: strictNullChecks yoqilganda (u strict ning bir qismi) null va undefined boshqa turlarga sig'maydi: string turidagi o'zgaruvchiga null yozib bo'lmaydi, string | null qiymatni esa tekshirmasdan satr kabi ishlatib bo'lmaydi. "Bo'sh bo'lishi mumkin" degan qiymat turida ochiq yoziladi — string | null, number | undefined — va har ishlatishdan oldin if, ?. yoki ?? bilan tekshiriladi.

Bu darsda

  • strictNullChecks nima qilishini uni o'chirib va yoqib ko'rasiz.
  • T | null va T | undefined ni qachon ishlatishni va qaysi API nimani qaytarishini bilasiz.
  • ?. va ?? ning turlarga ta'sirini tushunasiz; || va ?? farqini turlar orqali ko'rasiz.
  • localStorage dan kelgan matnni unknown orqali xavfsiz o'qiysiz.
  • vazifalar ning uchta modulini .ts ga ko'chirasiz va TypeScript topgan haqiqiy xatolarni tuzatasiz.

Oldin bilishingiz kerak: Type assertion, non-null va satisfies, Narrowing: turni toraytirish, ??, ?. va mantiqiy tayinlash.

1. Nega bu kerak?

null ni o'ylab topgan olim Tony Hoare 2009-yilda uni "milliard dollarlik xatom" deb atagan: o'nlab yillar davomida null dasturlarning eng ko'p yiqilish sababi bo'ldi. JavaScript'da ikkitasi bor — null ham, undefined ham (Ma'lumot turlari). Mana kundalik misol:

js
const params = new URLSearchParams("filtr=faol");
const sort = params.get("saralash");
console.log(sort.toUpperCase());

Konsolda:

text
TypeError: Cannot read properties of null (reading 'toUpperCase')

URL'da saralash yo'q — get null qaytardi. Bu kod yuz marta to'g'ri ishlashi mumkin (havolada parametr bor bo'lsa) va bir-biriga bog'liq bo'lmagan kunda yiqiladi. Butun 15-qism davomida biz TS18047 va TS18048 xabarlarini ko'rdik: "null (yoki undefined) bo'lishi mumkin". Bugun ularning ortidagi sozlamani — strictNullChecks ni — ochamiz.

2. strictNullChecks: o'chiq va yoqiq

2.1 O'chiq bo'lsa — TypeScript jim

Sozlamani bitta blokda o'chirib ko'ramiz (birinchi qatordagi @ts-options):

ts
// @ts-options: {"strictNullChecks": false}
const params = new URLSearchParams("filtr=faol");
const sort = params.get("saralash");
console.log(sort.toUpperCase());

tsc — xatosiz. Node esa:

text
TypeError: Cannot read properties of null (reading 'toUpperCase')

strictNullChecks o'chiq bo'lsa, null va undefined har qanday turga sig'adi: string turi aslida "satr yoki null yoki undefined" degani bo'lib qoladi. TypeScript bunday qiymatlarni hisobga olmaydi — xuddi JavaScript kabi.

2.2 Yoqiq bo'lsa — "avval tekshir"

ts
const params = new URLSearchParams("filtr=faol");
const sort = params.get("saralash");
console.log(sort.toUpperCase());

Kompilyator:

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

Endi get ning natija turi to'liq: string | null. null — alohida tur, string ga sig'maydi. Kundalik o'xshatish: "Bo'sh" degan qutini ham, "Satr" degan qutini ham bitta javonga qo'yasiz, lekin yorliqlari boshqa. Qutini ochishdan oldin yorlig'iga qaraysiz.

strictNullChecks — strict oilasining a'zosi. strict: true yoqsa, u ham yoqiladi; TypeScript 7 da strict standart holatda yoqiq (JSDoc darsida aytilgan). Kursdagi barcha bloklar va mashqlar papkasi uni yoqib ishlaydi.

2.3 Qiymat berishda ham

ts
let editingId: number = null;
const query: string = new URLSearchParams("").get("q");

Kompilyator:

text
TS2322: Type 'null' is not assignable to type 'number'.
TS2322: Type 'string | null' is not assignable to type 'string'.
  Type 'null' is not assignable to type 'string'.

Ikkinchi xabar zanjirli: TypeScript string | null dan aynan qaysi qism mos emasligini ko'rsatdi — null. Tuzatish — turda ochiq yozish: let editingId: number | null = null;. Endi null — ruxsat etilgan, rejalashtirilgan holat ("hech narsa tahrirlanmayapti").

Tekshirib ko'ring: strictNullChecks o'chiq bo'lsa, function find(): string { return undefined; } xato beradimi? Yoqiq bo'lsa-chi?

Javob

O'chiq — xatosiz: undefined string ga sig'adi. Yoqiq — TS2322: Type 'undefined' is not assignable to type 'string'. Funksiya imzosi "doim satr" deydi, undefined esa satr emas. Shartnomani to'g'rilang: (): string | undefined yoki satr qaytaring.

3. null yoki undefined?

3.1 Ikki xil "bo'shlik"

JavaScript'da ikkalasi ham "qiymat yo'q" degani, lekin odatda ma'nosi farq qiladi:

undefined null
Ma'nosi "berilmagan, yo'q" "ataylab bo'sh"
Qayerdan ixtiyoriy xususiyat va parametr, find, Map.get, arr[i] DOM, localStorage.getItem, searchParams.get, JSON
Turda x?: T yoki T | undefined T | null

Brauzer API'lari ko'pincha null qaytaradi: document.querySelector, getItem, get. JavaScript'ning o'z metodlari (find, Map.get, at) esa — undefined. TypeScript ularning turlarini aniq biladi, siz faqat hover qilib ko'rasiz.

3.2 O'z kodingizda — bitta tanlang

O'z ma'lumotlaringizda bitta qoida tanlash qulay. Ko'p jamoalar: "yo'q" uchun undefined (ixtiyoriy ? bilan tabiiy), "ataylab tozalangan" holat uchun null. vazifalar dagi tahrirId: number | null — "hech narsa tahrirlanmayapti", va bu holat ataylab o'rnatiladi. Ikkalasini ham bir joyda tekshirish kerak bo'lsa — Narrowing darsidagi x == null.

4. ?. va ?? — turlar tilida

4.1 ?. natijaga undefined qo'shadi

?. operatori zanjirni null/undefined da to'xtatadi va undefined qaytaradi. TypeScript buni turda ham ko'rsatadi:

ts
type Order = { guest?: { phone?: string } };

const order: Order = {};
const phoneLength: number = order.guest?.phone?.length;

Kompilyator:

text
TS2322: Type 'number | undefined' is not assignable to type 'number'.
  Type 'undefined' is not assignable to type 'number'.

length — son, lekin ?. zanjiri istalgan joyda to'xtashi mumkin. Shuning uchun butun ifodaning turi — number | undefined. ?. xatoni yo'qotmaydi — uni "qiymat yo'q" holatiga aylantiradi, va bu holat hali ham ko'rib chiqilishi kerak.

4.2 ?? — null va undefined ni olib tashlaydi

ts
type Order = { guest?: { phone?: string } };

const order: Order = { guest: {} };
const phone = order.guest?.phone ?? "telefon yo'q";
console.log(phone); // telefon yo'q

Hover: const phone: string. ?? o'ng tomonidagi standart qiymat bilan undefined ni almashtirdi va turdan uni olib tashladi. ?. va ?? — juftlik: biri xavfsiz o'qiydi, ikkinchisi bo'shliqni yopadi.

4.3 || va ??: tur bir xil, ma'no boshqa

ts
const servedCount = 0;
const a = servedCount || 10;
const b = servedCount ?? 10;
console.log(a, b); // 10 0

Ikkalasining turi ham number, TypeScript ularni farqlamaydi. Lekin || 0 ni ham "bo'sh" deb hisobladi (o'tgan darsdagi truthiness tuzog'i). "Bugun 0 ta buyurtma berildi" — haqiqiy qiymat, uni 10 ga almashtirish xato. Qoida: "qiymat yo'q bo'lsa" — ??, "qiymat falsy bo'lsa" — ||. Deyarli har doim ?? kerak.

??= — "faqat bo'sh bo'lsa yoz" (mantiqiy tayinlash): settings.city ??= "Toshkent". Turdan undefined keyingi qatorlarda yo'qoladi.

Tekshirib ko'ring: const n = [35000, 28000].find((p) => p > 30000)?.toFixed(0) ?? "yo'q"; — n ning turi va qiymati qanday?

Javob

Turi — string: find — number | undefined, ?.toFixed(0) — string | undefined, ?? "yo'q" — string. Qiymati — "35000": 35 000 — 30 000 dan katta birinchi narx.

5. Tashqi qiymat: null dan unknown gacha

localStorage dan saqlangan sozlamani o'qish — bugungi mavzuning hamma qismini birlashtiradi:

  1. getItem — string | null (kalit yo'q bo'lishi mumkin).
  2. JSON.parse — any (uni darhol unknown ga olamiz, any va unknown).
  3. Ichidagi maydonlar — har biri tekshiriladi va bo'lmasa — standart qiymat.
ts
type Settings = { readonly percent: number; readonly city: string };
type StorageLike = { getItem(key: string): string | null };

const DEFAULTS: Settings = { percent: 10, city: "Toshkent" };

function readJson(storage: StorageLike, key: string): unknown {
  const text = storage.getItem(key);
  if (text === null) {
    return undefined;
  }
  try {
    return JSON.parse(text);
  } catch {
    return undefined;
  }
}

function loadSettings(storage: StorageLike): Settings {
  const raw = readJson(storage, "bahor:sozlama");
  if (typeof raw !== "object" || raw === null) {
    return DEFAULTS;
  }
  const percent =
    "percent" in raw && typeof raw.percent === "number"
      ? raw.percent
      : DEFAULTS.percent;
  const city =
    "city" in raw && typeof raw.city === "string" && raw.city !== ""
      ? raw.city
      : DEFAULTS.city;
  return { percent, city };
}

const empty: StorageLike = { getItem: () => null };
const broken: StorageLike = { getItem: () => "{" };
const saved: StorageLike = {
  getItem: () => '{"percent":15,"city":""}',
};
console.log(loadSettings(empty));
console.log(loadSettings(broken).percent);
console.log(loadSettings(saved));

Konsolda:

text
{ percent: 10, city: 'Toshkent' }
10
{ percent: 15, city: 'Toshkent' }

Qiymat bosqichma-bosqich toraydi — har bosqichda "bo'sh" holat standart qiymatga yo'naltiriladi:

flowchart TD
  A["getItem(key): string | null"] --> B{"null mi?"}
  B -- "ha" --> D["DEFAULTS"]
  B -- "yo'q: string" --> C["JSON.parse → unknown"]
  C --> E{"obyektmi, null emasmi?"}
  E -- "yo'q" --> D
  E -- "ha: object" --> F{"har maydon: bor va<br/>turi to'g'rimi?"}
  F -- "yo'q" --> G["shu maydon — standart"]
  F -- "ha" --> H["saqlangan qiymat"]

Bir nechta narsaga e'tibor bering:

  • StorageLike — localStorage ning bizga kerakli qismi: getItem metodi. Haqiqiy localStorage ham unga mos (Strukturaviy tiplash), testlarda esa oddiy obyekt berdik — brauzersiz.
  • text === null tekshiruvidan keyin text — string, JSON.parse ga beriladi.
  • readJson natijasi — unknown: kalit yo'q, buzuq JSON va null — hammasi bir xil "noma'lum". Keyingi tekshiruvlar har maydonni alohida toraytiradi.
  • Saqlangan city bo'sh satr edi — standart shahar qo'yildi, percent esa saqlandi. Bitta buzuq maydon butun sozlamani buzmadi.

6. TypeScript nimani ushlamaydi

strictNullChecks yoqiq bo'lsa ham, uch joyda null/undefined jim o'tib ketadi:

  • ! va as — o'tgan dars: "bu null emas" degan va'da tekshirilmaydi.
  • Massiv indeksi — noUncheckedIndexedAccess siz prices[5] — number, aslida undefined (Massiv va tuple).
  • any — JSON.parse(text).city.trim() — city yo'q bo'lsa ham, tsc jim.

Yana bir nozik joy — ?. hamma narsani "yashirishi". order?.guest?.phone?.length ?? 0 — xatosiz, lekin order ning o'zi undefined bo'lishi xato bo'lsa-chi? Unda 0 ekranda chiqadi, xato esa yashirinadi. ?. ni faqat "bo'lmasligi mumkin" deb rejalashtirilgan joyda ishlating; "bo'lishi shart" bo'lgan joyda — tekshiruv va throw.

7. Ko'p uchraydigan xatolar

7.1 Turga null ni yozmaslik

let editingId: number = null — TS2322. Tuzatish: number | null. Tur haqiqatni aytsin.

7.2 Brauzer API natijasini ko'r-ko'rona ishlatish

params.get("q").trim(), localStorage.getItem("k").length — TS18047. Tuzatish: ?? "" yoki if (x === null) return ….

7.3 || bilan standart qiymat

count || 10 — 0 yo'qoladi. Tuzatish: count ?? 10.

7.4 ?. dan keyin natijani "tayyor" deb o'ylash

const len: number = a?.b?.length — TS2322, natija number | undefined. Tuzatish: ?? 0 yoki tekshiruv.

8. Mashqlar

1-mashq (oson): Natija turi qanday?

new URLSearchParams("").get("q") turi: string | [:null]. [5000, 8000].find((p) => p > 6000) turi: number | [:undefined]. order.note ?? "izohsiz" (note?: string) turi: .

Yechim

get — brauzer API, string | null. find — JavaScript metodi, topmasa undefined: number | undefined. ?? bo'shliqni yopdi — string.

2-mashq (o'rta): Kassa hisobini tuzating

Kod tsc dan o'tmaydi. Uchala xatoni tuzating: chegirma kodi yo'q bo'lsa — chegirmasiz; noma'lum kod — chegirmasiz; servedToday 0 bo'lsa ham to'g'ri ko'rsatilsin.

ts
const DISCOUNTS = new Map([
  ["BAHOR10", 10],
  ["DOST5", 5],
]);

function finalPrice(sum: number, code: string | null): number {
  const percent = DISCOUNTS.get(code.toUpperCase());
  return sum - (sum * percent) / 100;
}

const servedToday: number | undefined = 0;
console.log(finalPrice(70000, null), servedToday || "noma'lum");

Kompilyator:

text
TS18047: 'code' is possibly 'null'.
TS18048: 'percent' is possibly 'undefined'.

TypeScript aytyapti: «code null bo'lishi mumkin» va «percent undefined bo'lishi mumkin». Ikkalasini ham tekshirmasdan ishlatyapmiz.

Uchinchi muammoni tsc ko'rsatmadi — u mantiq xatosi. Qaysi qatorda?

Yechim
ts
const DISCOUNTS = new Map([
  ["BAHOR10", 10],
  ["DOST5", 5],
]);

function finalPrice(sum: number, code: string | null): number {
  const percent = DISCOUNTS.get(code?.toUpperCase() ?? "") ?? 0;
  return sum - (sum * percent) / 100;
}

const servedToday: number | undefined = 0;
console.log(finalPrice(70000, null)); // 70000
console.log(servedToday ?? "noma'lum"); // 0
console.log(finalPrice(70000, "bahor10")); // 63000
  • code?.toUpperCase() ?? "" — kod yo'q bo'lsa, bo'sh satr bilan qidiramiz (u Map da yo'q).
  • DISCOUNTS.get(…) ?? 0 — noma'lum kod — 0 % chegirma. percent endi number.
  • Uchinchi xato — servedToday || "noma'lum": 0 "noma'lum" bo'lib chiqardi. ?? bilan — 0. tsc buni ko'rmadi: ikkala yozuv ham turi jihatidan to'g'ri.

3-mashq (qiyin): Bron vaqtini URL'dan o'qish

readBooking(url: string) funksiyasini yozing: URL'dagi ?mehmon=…&soat=… parametrlaridan bron obyekti { guest: string; hour: number } yasaydi. Mehmon yo'q yoki bo'sh bo'lsa — null qaytsin. Soat yo'q, son emas yoki 10–22 oralig'idan tashqarida bo'lsa — standart 19. Natija turi: { guest: string; hour: number } | null.

Ishora: new URL(url).searchParams.get(…) — string | null; Number(text) va Number.isInteger (Matn ↔ son).

Yechim
ts
type Booking = { guest: string; hour: number };

function readBooking(url: string): Booking | null {
  const params = new URL(url).searchParams;
  const guest = params.get("mehmon")?.trim() ?? "";
  if (guest === "") {
    return null;
  }
  const hourText = params.get("soat");
  const hour = hourText === null ? Number.NaN : Number(hourText);
  const valid = Number.isInteger(hour) && hour >= 10 && hour <= 22;
  return { guest, hour: valid ? hour : 19 };
}

const base = "https://example.com/bron";
console.log(readBooking(`${base}?mehmon=Malika&soat=20`));
console.log(readBooking(`${base}?mehmon=Bobur&soat=23`));
console.log(readBooking(`${base}?soat=20`));

Konsolda:

text
{ guest: 'Malika', hour: 20 }
{ guest: 'Bobur', hour: 19 }
null
  • params.get("mehmon")?.trim() ?? "" — uch holat bitta qatorda: parametr yo'q (null), bo'sh joylardan iborat, bor.
  • hourText === null ? Number.NaN : … — Number(null) — 0, bu esa "soat 0" bo'lib qolardi. null ni alohida ko'rib, NaN ga aylantirdik — keyingi tekshiruv uni rad etadi.
  • Natija turi Booking | null — chaqiruvchi null ni tekshirishga majbur: "bron yo'q" holati unutilmaydi.

4-mashq: Vazifalar qadami — holat, saqlash, marshrut .ts ga

Uchta modul DOM'siz, Node'da testlanadi va null qaytaradigan brauzer API'lariga tayanadi: localStorage.getItem, searchParams.get, tahrirId: null. Ular .ts ga o'tadi — va strictNullChecks o'z ishini ko'rsatadi.

  • Branch: refactor/null-xavfsiz
  • Commit: refactor: holat, saqlash, marshrut — .ts, null xavfsiz, tanasi: localStorage.getItem va searchParams.get — string | null
  1. git mv bilan uchala faylni .ts ga o'tkazing va npm run tip — xatolarni sanang.
  2. Parametr va natija turlarini yozing. Avval "sodda" variant bilan sinang: temaniOl(): string, yukla(): VazifaMalumoti[], tahrirId: number, vazifaniTop(): Vazifa. Nechta xato?
  3. Haqiqiy turlar bilan qolgan xatolarni tuzating. Importlar — "./holat.ts" kabi fayl nomi aynan.
  4. Testlarda import yo'llari: ../assets/js/holat.js → holat.ts (va boshqalar). sw.js — VERSIYA = "v5-3".
Yechim

1-qadam: faqat nomi o'zgardi — npx tsc --noEmit 29 xato topdi: TS7006 (parametr turi yo'q) — 22, TS18046 ('xato' is of type 'unknown') — 6, TS2345 — 1. TS18046 larning hammasi saqlash da: catch (xato) ichida xato.name — unknown darsidagi holat.

2-qadam: "sodda" turlar. JavaScript'da shunday "tuyuladi": tema — satr, yuklangan ro'yxat — massiv, tahrirId — son. strictNullChecks 9 ta xato topdi (bayroqni o'chirib sinadik — 0 ta):

text
assets/js/holat.ts(46,3): error TS2322: Type 'null' is not assignable to type 'number'.
assets/js/holat.ts(74,3): error TS2322: Type 'Vazifa | undefined' is not assignable to type 'Vazifa'.
assets/js/saqlash.ts(38,5): error TS2322: Type 'null' is not assignable to type 'VazifaMalumoti[]'.
assets/js/saqlash.ts(103,5): error TS2322: Type 'string | null' is not assignable to type 'string'.
… (jami 9)

Har biri — haqiqiy holat: tahrirId boshida null; vazifaniTop topmasa undefined qaytaradi; yukla xotira bo'sh bo'lsa null qaytaradi; getItem — string | null. "Sodda" turlar bu holatlarni yashirardi.

3-qadam: haqiqiy turlar. holat.ts dagi holat turi:

ts
export type Holat = {
  vazifalar: VazifalarRoyxati;
  filtr: Filtr;
  qidiruv: string; // URL'ga yozilmaydi: har harfda tarix yozuvi bo'lmasin
  saralash: Saralash; // URL'da: ?saralash=alifbo
  // null — hech narsa tahrirlanmayapti. Turi yozilmasa, TS uni
  // boshlang'ich qiymatdan "null" deb oladi va id yozib bo'lmaydi
  tahrirId: number | null;
  tarmoq: TarmoqHolati;
};

Izohdagi gap — muhim nozik joy: const holat = { tahrirId: null, … } turini yozmasangiz, TypeScript tahrirId ni null turida chiqaradi (literal null, u kengaymaydi). Keyin holat.tahrirId = 5 — xato. Shuning uchun holat turi alohida yoziladi. Filtr, Saralash, TarmoqHolati — Discriminated union qadamidagi union'lar.

Funksiyalar endi "bo'lmasligi mumkin"ni ochiq aytadi: vazifaniTop(id: number): Vazifa | undefined, yukla(): VazifaMalumoti[] | null, temaniOl(): string | null ("tanlov saqlanmagan"). saqlash.ts da catch dagi unknown uchun ikki kichik yordamchi:

ts
// catch'dagi qiymat — unknown: throw istalgan narsani tashlashi mumkin.
// localStorage DOMException (Error) tashlaydi; boshqasi — matn qilib
function xatoNomi(xato: unknown): string {
  return xato instanceof Error ? xato.name : String(xato);
}

Qolgan 2 ta haqiqiy xato — marshrut.ts da, searchParams.get():

text
assets/js/marshrut.ts(20,29): error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'T'.
assets/js/marshrut.ts(20,39): error TS2322: Type 'string | null' is not assignable to type 'T'.

Bu Union darsidagi «includes tuzog'i» — null bilan. Tuzatish ham o'sha — find va ??:

ts
// Oldin (marshrut.js)
const qiymat = new URL(manzil).searchParams.get(nomi);
return ruxsatlar.includes(qiymat) ? qiymat : standart;

// Keyin (marshrut.ts)
// get() — string | null: parametr yo'q bo'lsa null. find ruxsat
// etilganini T turida qaytaradi; null hech biriga teng emas
const qiymat = new URL(manzil).searchParams.get(nomi);
return ruxsatlar.find((ruxsat) => ruxsat === qiymat) ?? standart;

Funksiya imzosi: parametrniOl<T extends string>(manzil: string, nomi: string, ruxsatlar: readonly T[], standart: T): T. <T extends string> — generic: "T — qandaydir satr turi". filtrniOl uni Filtr ro'yxati bilan chaqiradi va Filtr oladi, saralashniOl — Saralash. Bitta funksiya ikki xil union bilan ishlaydi. Generic'larni Generics: turni parametr qilish darsida o'zingiz yozasiz. holat.ts dagi chuqurMuzlat<T extends object>(obyekt: T): Readonly<T> ham shunday.

4-qadam. Testlar .js bo'lib qoladi, faqat import yo'li o'zgaradi: "../assets/js/holat.ts". Node 24 .ts ni o'zi o'qiydi. sw.js da VERSIYA = "v5-3".

Tekshiruv: npm test — 137/137 (Node .ts ni to'g'ridan-to'g'ri), tip, lint, format:check — toza. 159 ta brauzer tekshiruvi dist/ da — 159/159.

Commit va PR:

bash
git switch -c refactor/null-xavfsiz
git mv assets/js/holat.js assets/js/holat.ts
git mv assets/js/saqlash.js assets/js/saqlash.ts
git mv assets/js/marshrut.js assets/js/marshrut.ts
# turlar, importlar, testlardagi yo'llar, sw VERSIYA
npm run build && npm test && npm run tip
npm run lint && npm run format:check
git add .
git commit -m "refactor: holat, saqlash, marshrut — .ts, null xavfsiz" \
  -m "localStorage.getItem va searchParams.get — string | null"
git push -u origin refactor/null-xavfsiz
gh pr create --fill
gh pr merge --merge

Sarlavha — 56 belgi. Diff: 14 fayl, +161 −113. Bu qadamdagi xatolar soni bosqichma-bosqich:

vazifalar #15: tsc xatolari bosqichlar bo'yicha
  • faqat .ts nomi29 xato
  • sodda turlarstrictNullChecks9 xato
  • haqiqiy turlarsearchParams.get2 xato
  • tuzatilgach0 xato

Manba: O'lchandi: tsc 7.0.2 --noEmit, vazifalar #15 (holat, saqlash, marshrut), Node 24.21.0, 2026-10-06

9 ta xatoning hammasi strictNullChecks ning ishi: bayroq o'chiq bo'lsa, "sodda" turlar bilan ham tsc 0 deydi — va bu to'qqizta holat ishlash paytida yashirin qoladi.

9. Real ishda

  • Har bir DOM kodi null bilan boshlanadi: document.querySelector(…) — Element | null. TypeScript va DOM qadamida vazifalar ning DOM modullari 106 ta possibly 'null' xatosini beradi.
  • Server javoblari va ma'lumotlar bazasi — null maydonlar odatiy: "telefon kiritilmagan", "hali to'lanmagan". Ularning turida | null bo'lishi interfeysni (UI) ham to'g'ri yozishga majbur qiladi.
  • Jamoalarda strictNullChecks siz TypeScript loyihasi — "yarim" TypeScript hisoblanadi. Eski loyihalarni ko'chirishda ham bu bayroq birinchi yoqiladiganlar qatorida.
  • Intervyu: "strictNullChecks nima qiladi?", "null va undefined farqi?", "?? va || farqi?" — tez-tez so'raladi.

Xulosa

  • strictNullChecks (strict ning a'zosi) — null va undefined alohida turlar: ular boshqa turlarga sig'maydi va tekshiruvsiz ishlatilmaydi (TS18047, TS18048, TS2322).
  • "Bo'sh bo'lishi mumkin" — turda ochiq: T | null (ataylab bo'sh, brauzer API'lari) yoki T | undefined / x?: T (berilmagan).
  • ?. — natijaga undefined qo'shadi, ?? — uni olib tashlaydi. Standart qiymat uchun || emas, ??.
  • Tashqi qiymat: string | null → JSON.parse → unknown → har maydon tekshiriladi, bo'lmasa — standart.
  • !, as, any va tekshirilmagan indeks — strictNullChecks ni chetlab o'tadi.

Keyingi dars: Kengaytirish, kesishma va declaration merging — turlarni extends va & bilan birlashtiramiz, interface lar birlashishini chuqur ko'ramiz.

Manbalar

  • TSConfig: strictNullChecks — typescriptlang.org/tsconfig#strictNullChecks
  • TypeScript Handbook: "Everyday Types" → null and undefined — typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined
  • Tony Hoare, "Null References: The Billion Dollar Mistake" (QCon London, 2009) — infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
  • MDN: URLSearchParams.get(), Storage.getItem() — developer.mozilla.org/docs/Web/API
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript'da null va undefined bilan xavfsiz ishlash: strictNullChecks — IlmHamroh