IlmHamroh
JavaScript Full-stack/15-qism. TypeScript34/47-dars18 daqiqa
Mundarija (29)

TypeScript strict bayroqlari: strict ichida nima bor va undan tashqaridagi himoyalar

Qisqacha: "strict": true — bitta kalit, lekin u sakkizta tekshiruvni yoqadi: noImplicitAny, strictNullChecks, strictFunctionTypes va boshqalar. TypeScript 6 va 7 da u sukut bo'yicha yoqiq. strict ga kirmaydigan, lekin haqiqiy xato ushlaydigan bayroqlar ham bor: noUncheckedIndexedAccess (massiv[i] — undefined bo'lishi mumkin), exactOptionalPropertyTypes, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noUnused*. Ularni yoqish narxi — bir necha xatoni tuzatish; vazifalar da bu ikkita xato bo'ldi.

Bu darsda

  • strict yoqadigan sakkiz bayroqni va har biri qaysi xato kodini berishini bilasiz.
  • strict ga kirmaydigan yetti bayroqni yoqib, har birining xabarini o'qiy olasiz.
  • Bayroqni yoqishdan oldin uning "narxini" — loyihada nechta xato chiqishini — o'lchaysiz.
  • Eng qat'iy sozlamada ham TypeScript nimani ushlamasligini bilasiz (!, as).
  • vazifalar da qat'iy bayroqlarni yoqib, qidiruv.ts dagi ikki haqiqiy xatoni tuzatasiz.

Oldin bilishingiz kerak: tsconfig.json chuqur, null va undefined bilan xavfsiz ishlash, Massiv va tuple turlari.

1. Nega bu kerak?

O'tgan darsda tsconfig ning tuzilishini ko'rdik va strict TypeScript 7 da sukut bo'yicha yoqiq ekanini tekshirdik. Lekin strict aslida nima? Bitta tekshiruvmi yoki bir nechtasi? Va undan tashqarida yana nimalar bor? Massiv va tuple turlari darsida noUncheckedIndexedAccess ni ko'rib, "uning narxini keyinroq to'liq ko'ramiz" degandik. Bugun — o'sha dars.

Sardor «Bahor» kassasi uchun eski loyihadan kod oldi. U yerda "strict": false edi va tsc hech narsa demasdi. Yangi loyihada (TypeScript 7.0.2, sozlamasiz — demak strict yoqiq) xuddi shu kod:

ts
function addTip(total, tip) { return total + tip; }
const menu = new Map<string, number>([["osh", 35000]]);
const price: number = menu.get("manti");
type MenuItem = { name: string };
type Drink = MenuItem & { ml: number };
const show: (m: MenuItem) => void = (d: Drink) =>
  console.log(d.ml);
function format(this: { cur: string }, n: number) {
  return `${n} ${this.cur}`;
}
format.call({ cur: "so'm" }, "35000");
class Order { table: number; }
const loose = {
  inc() {
    return function () {
      return this.n;
    };
  },
};
try {
  JSON.parse("{");
} catch (e) {
  console.log(e.message);
}
const it = [1, 2].values();
const v: number = it.next().value;

Kompilyator:

text
TS7006: Parameter 'total' implicitly has an 'any' type.
TS7006: Parameter 'tip' implicitly has an 'any' type.
TS2322: Type 'number | undefined' is not assignable to type 'number'.
  Type 'undefined' is not assignable to type 'number'.
TS2322: Type '(d: Drink) => void' is not assignable to type '(m: MenuItem) => void'.
  Types of parameters 'd' and 'm' are incompatible.
    Type 'MenuItem' is not assignable to type 'Drink'.
      Property 'ml' is missing in type 'MenuItem' but required in type '{ ml: number; }'.
TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
TS2564: Property 'table' has no initializer and is not definitely assigned in the constructor.
TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
TS18046: 'e' is of type 'unknown'.
TS2322: Type 'number | undefined' is not assignable to type 'number'.
  Type 'undefined' is not assignable to type 'number'.

TypeScript aytyapti, qisqasi: "parametr turi yashirin any" (TS7006), "undefined ni number ga berib bo'lmaydi" (TS2322), "table ga boshlang'ich qiymat berilmagan" (TS2564), "this ning turi noma'lum" (TS2683), "e — unknown" (TS18046). Har birini quyidagi jadvalda o'z bayrog'i bilan ko'ramiz.

To'qqizta xato. "strict": false bilan — nol. Ya'ni eski loyihada bu to'qqiz joy "ishlayotgan" kod sifatida yashagan: price — aslida undefined, format ga satr ketgan, Order ning table i — undefined. Har biri ertami-kechmi mijoz oldida ochiladi.

Har xato qaysi tekshiruvdan kelganini bilish uchun strict ni bo'laklarga ajratamiz.

2. strict ichida — sakkiz bayroq

2.1 Ro'yxat

strict: true quyidagilarni yoqadi. Har birini alohida o'chirib, yuqoridagi to'qqiz xatodan qaysi biri yo'qolishini TypeScript 7.0.2 da tekshirdik:

Bayroq Nimani tekshiradi Xato kodi
noImplicitAny turi chiqarib bo'lmaydigan joyda yashirin any TS7006
strictNullChecks null/undefined alohida tur TS2322, TS2564
strictFunctionTypes parametrlar kontravariant TS2322 (zanjir)
strictBindCallApply call/bind/apply argumentlari TS2345
strictPropertyInitialization klass maydoni konstruktorda to'ldirilgan TS2564
noImplicitThis turi noma'lum this TS2683
useUnknownInCatchVariables catch (e) — unknown, any emas TS18046
strictBuiltinIteratorReturn iterator tugaganda value — undefined TS2322

To'qqizinchisi — alwaysStrict (har faylga "use strict"). U TypeScript 6 dan beri doim yoqiq: "alwaysStrict": false yozsangiz, TypeScript 7.0.2 TS5108: Option 'alwaysStrict=false' has been removed. beradi.

strictNullChecks o'chirilganda uch xato yo'qoldi: menu.get (number | undefined), table maydoni va iterator value i. strictPropertyInitialization va strictBuiltinIteratorReturn unga tayanadi: null alohida tur bo'lmasa, "to'ldirilmagan maydon" yoki "undefined qiymat" haqida gapirib bo'lmaydi.

2.2 Ko'rganlarimiz va yangilari

Ro'yxatdagi bayroqlarning ko'pi tanish:

  • noImplicitAny — Tur annotatsiyasi darsidan: parametr turi yozilmasa — TS7006.
  • strictNullChecks — null va undefined darsining asosi. vazifalar da u 9 xato topgan edi (sodda turlar yozilganda), o'chirilsa — 0.
  • strictFunctionTypes — Branded types va variance darsidagi kontravariantlik.
  • useUnknownInCatchVariables — catch (e) dagi e — unknown: avval instanceof Error bilan toraytiriladi (Async kod va xatolarni tiplash darsida batafsil).

Yangilari — uchta:

strictBindCallApply — format.call(obj, "35000") ni oddiy chaqiruv kabi tekshiradi. Usiz call ning argumentlari any bo'lardi. this parametri (this: { cur: string }) — funksiya qaysi obyekt bilan chaqirilishini aytadi (Function overload va this turi).

strictPropertyInitialization — klassdagi table: number; maydoniga konstruktorda qiymat berilmasa — TS2564: "table xususiyatida boshlang'ich qiymat yo'q va konstruktorda aniq berilmagan". Tuzatish: boshlang'ich qiymat (table = 0), konstruktorda berish yoki turini number | undefined qilish.

strictBuiltinIteratorReturn (TypeScript 5.6 dan) — it.next().value turi number | undefined: iterator tugaganda { done: true, value: undefined } qaytaradi (Iteratsiya protokoli). Bayroqsiz u any bo'lardi.

Tekshirib ko'ring: strict: true va strictNullChecks: false birga yozilsa, nima bo'ladi?

Javob

strict dagi qolgan yetti bayroq yoqiq qoladi, strictNullChecks esa o'chadi. Aniq yozilgan bayroq strict dan ustun. Bu ko'chishda foydali: strict ni yoqib, eng "qimmat" bayroqni vaqtincha o'chirib turish mumkin. vazifalar da 15-qadamda aynan shunday o'lchangan: --strictNullChecks false bilan 9 xato 0 ga tushgan.

3. strict dan tashqarida: yetti qo'shimcha bayroq

Bu bayroqlar strict ga kirmaydi — ularni alohida yozasiz. Har birini saytdagi blokning birinchi qatoridagi sozlama bilan yoqamiz.

3.1 noUncheckedIndexedAccess — indeks undefined bo'lishi mumkin

Massiv va tuple darsidagi tanish bayroq — endi obyektlar bilan ham:

ts
// @ts-options: {"noUncheckedIndexedAccess": true}
const prices: Record<string, number> = { osh: 35000 };
const p = prices["manti"];
console.log(p.toFixed(0));
const list = [35000, 28000];
const first = list[0];
console.log(first + 1);

Kompilyator:

text
TS18048: 'p' is possibly 'undefined'.
TS18048: 'first' is possibly 'undefined'.

TypeScript aytyapti: "p undefined bo'lishi mumkin" va "first undefined bo'lishi mumkin".

Record<string, number> dagi istalgan kalit (Index signature va Record) va massivning istalgan indeksi — T | undefined. Birinchi xato haqiqiy: menyuda manti narxi yo'q. Ikkinchisi — "ortiqcha ehtiyot": list[0] aniq bor. Bu bayroqning narxi shu: kompilyator ro'yxat uzunligini bilmaydi, siz esa har gal tekshirasiz. for...of, map, find ga ta'sir qilmaydi.

3.2 exactOptionalPropertyTypes — "yo'q" va "undefined" boshqa-boshqa

Mapped types darsida bu bayroq Partial + spread tuzog'ini ushlagan edi:

ts
// @ts-options: {"exactOptionalPropertyTypes": true}
type Guest = { name: string; phone?: string };
const g: Guest = { name: "Dilshod aka", phone: undefined };

Kompilyator:

text
TS2375: Type '{ name: string; phone: undefined; }' is not assignable to type 'Guest' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
  Types of property 'phone' are incompatible.
    Type 'undefined' is not assignable to type 'string'.

TypeScript aytyapti: "phone: undefined li obyektni Guest ga berib bo'lmaydi — exactOptionalPropertyTypes yoqiq; xohlasangiz, turga undefined ni qo'shing". Pastki qator sababni aytadi: "undefined ni string ga berib bo'lmaydi".

phone?: string endi "yoki yo'q, yoki satr" — undefined qiymat emas. "phone" in g tekshiruvi va Object.keys natijasi tur bilan mos bo'ladi. Haqiqatan "undefined ham mumkin" desangiz — phone?: string | undefined deb aniq yozasiz.

3.3 noImplicitOverride — ota-klass metodini bilmasdan yopish

ts
// @ts-options: {"noImplicitOverride": true}
class Dish {
  label(): string {
    return "taom";
  }
}
class Drink extends Dish {
  label(): string {
    return "ichimlik";
  }
}

Kompilyator:

text
TS4114: This member must have an 'override' modifier because it overrides a member in the base class 'Dish'.

"Bu a'zo Dish dagi a'zoni almashtiradi, shuning uchun override belgisi kerak". override label() — "bilib turib almashtiryapman". Foydasi: ota-klassda label nomi o'zgarsa, override li metod darhol xato beradi (Klasslar TypeScript'da).

3.4 noImplicitReturns — ba'zi yo'llarda return yo'q

ts
// @ts-options: {"noImplicitReturns": true}
function discount(total: number) {
  if (total > 100000) {
    return total * 0.1;
  }
}

Kompilyator:

text
TS7030: Not all code paths return a value.

"Kodning hamma yo'llari qiymat qaytarmaydi". 100 000 dan kam summada funksiya jim undefined qaytaradi. Tuzatish: oxirida return 0;.

3.5 noFallthroughCasesInSwitch — break unutilgan

ts
// @ts-options: {"noFallthroughCasesInSwitch": true}
type Status = "yangi" | "tayyor" | "bekor";
function label(s: Status): string {
  let text = "";
  switch (s) {
    case "yangi":
      text = "Yangi";
    case "tayyor":
      text = "Tayyor";
      break;
    case "bekor":
      text = "Bekor";
  }
  return text;
}

Kompilyator:

text
TS7029: Fallthrough case in switch.

"switch da keyingi case ga tushib ketish". "yangi" dan keyin break yo'q — kod "tayyor" qismiga ham o'tadi va yangi buyurtma "Tayyor" bo'lib ko'rinadi (switch darsidagi klassik xato). Oxirgi case ga break shart emas — undan keyin tushadigan joy yo'q.

3.6 noUnusedLocals va noUnusedParameters

ts
// @ts-options: {"noUnusedLocals": true, "noUnusedParameters": true}
export function total(prices: number[], currency: string): number {
  const rate = 1.1;
  return prices.reduce((sum, p) => sum + p, 0);
}

Kompilyator:

text
TS6133: 'currency' is declared but its value is never read.
TS6133: 'rate' is declared but its value is never read.

"E'lon qilingan, lekin qiymati hech qachon o'qilmagan". Ko'pincha bu — tugallanmagan ish: rate ni qo'llash unutilgan. Ishlatilmaydigan parametrni ataylab qoldirish kerak bo'lsa — nomini _ bilan boshlang (_currency). ESLint'dagi no-unused-vars (ESLint va Prettier) xuddi shuni qiladi — loyihada odatda bittasi yetadi.

3.7 noPropertyAccessFromIndexSignature — uslub bayrog'i

ts
// @ts-options: {"noPropertyAccessFromIndexSignature": true}
const prices: Record<string, number> = { osh: 35000 };
console.log(prices.osh);

Kompilyator:

text
TS4111: Property 'osh' comes from an index signature, so it must be accessed with ['osh'].

"osh indeks imzosidan keladi, shuning uchun ['osh'] bilan murojaat qiling". Maqsad — o'quvchiga ko'rsatish: prices.osh "aniq maydon" emas, "lug'atdan qidiruv". Bu xato topmaydi, faqat yozuv uslubini talab qiladi. vazifalar da u 13 "xato" berdi — hammasi uslub — va yoqilmadi.

Tekshirib ko'ring: Qaysi bayroqlar haqiqiy xatolarni ushlaydi, qaysilari asosan uslub haqida?

Javob

Haqiqiy xatolar: noUncheckedIndexedAccess (yo'q element), exactOptionalPropertyTypes (undefined spread), noImplicitReturns (jim undefined), noFallthroughCasesInSwitch (unutilgan break), noImplicitOverride (nomi o'zgargan metod). Asosan tartib: noUnused* (tugallanmagan ishni ko'rsatadi, lekin dastur buzilmaydi) va noPropertyAccessFromIndexSignature (faqat yozuv shakli).

4. TypeScript 7: sukut bo'yicha nima yoqiq

Bayroq Sozlamasiz tsc --init faylida
strict (8 bayroq) yoqiq (TS 6 dan) true
noUncheckedIndexedAccess o'chiq true
exactOptionalPropertyTypes o'chiq true
noImplicitReturns, noImplicitOverride, noUnused*, noFallthroughCasesInSwitch, noPropertyAccessFromIndexSignature o'chiq izohda (//) — "Style Options"

Ikki qat'iy bayroq sozlamasiz o'chiq, lekin tsc --init (TypeScript 7.0.2) yaratgan faylda yoqiq — biz uni scratch papkada yaratib tekshirdik. Ya'ni yangi loyiha ularsiz emas, ular bilan boshlanadi. Saytdagi bloklarimiz va TS Playground esa strict bilan, lekin bu ikkisisiz ishlaydi — shuning uchun darsdagi misollarda ularni birinchi qatorda alohida yoqdik.

Rasmiy manbalar: Microsoft, "Announcing TypeScript 6.0" (2026-03-23) — strict sukut bo'yicha true; "Announcing TypeScript 7.0" (2026-07-08) — xuddi shu standartlar (havolalar «Manbalar» da).

5. Bayroqni yoqishdan oldin — narxini o'lchang

Katta loyihada bayroqni bir zumda yoqish yuzlab xato berishi mumkin. To'g'ri tartib:

flowchart TD
  A["Bayroqni tanlash"] --> B["npx tsc --noEmit --bayroq"]
  B --> C{"Nechta xato?"}
  C -- "0" --> D["tsconfig ga yozing"]
  C -- "oz, haqiqiy" --> E["tuzating, keyin yozing"]
  C -- "ko'p, uslub" --> F["yoqmang yoki keyinga"]
  E --> D

Kalit — buyruq qatoridagi bayroq: npx tsc --noEmit --noUncheckedIndexedAccess. U tsconfig.json ni o'zgartirmaydi, faqat shu bir marta qo'shib tekshiradi. Har bayroqni alohida ishga tushiring — shunda qaysi xato qaysi bayroqdan ekani aniq.

vazifalar da shu usul bilan o'lchangan raqamlar (pastdagi Vazifalar qadamida batafsil):

vazifalar: bayroq yoqilganda nechta xato chiqdi
  • strictNullChecks (#15)sodda turlar bilan9 xato
  • noUncheckedIndexedAccesshaqiqiy — qidiruv.ts2 xato
  • noPropertyAccess…uslub — yoqilmadi13 xato
  • qolgan 6 bayroq0 xato

Manba: O'lchandi: tsc 7.0.2 --noEmit --<bayroq>, vazifalar holatlar/15 va /26, 2026-10-06 (sinov/15/QADAMLAR.md)

6. TypeScript ushlamaydigan tuzoq: ! va as bayroqlarni chetlab o'tadi

Eng qat'iy sozlamada ham dasturchi kompilyatorga "menga ishon" deya oladi. Ikki eng keng tarqalgan yo'l:

ts
// @ts-options: {"noUncheckedIndexedAccess": true}
const prices = [35000, 28000];
const p = prices[5]!;
console.log(p.toFixed(0));

tsc — xatosiz. Node esa:

text
TypeError: Cannot read properties of undefined (reading 'toFixed')

! — non-null assertion: "bu undefined emas, men bilaman". noUncheckedIndexedAccess qo'shgan himoyani bitta belgi bekor qildi. Klass maydonida ham xuddi shunday:

ts
class Order {
  table!: number;
}
const o = new Order();
console.log(o.table.toFixed(0));

table!: number — "bu maydonni kimdir keyin to'ldiradi" (definite assignment). strictPropertyInitialization jim qoldi, table esa undefined.

Qoida: ! va as — bayroqlarning "o'chirish tugmasi". Ular kerak bo'ladigan kam holatlar bor, lekin har birida izoh yozing: nega bu yerda undefined bo'lishi mumkin emas. vazifalar dagi qidiruv.ts da aynan shu sababli ! emas, tekshiruv tanlangan (pastda).

7. Ko'p uchraydigan xatolar

7.1 strict: false bilan "tez boshlash"

Xatolar yo'qolmaydi — ular ishlash paytiga ko'chadi. Tuzatish: strict ni yoqing, ko'chish paytida faqat eng qimmat bayroqni vaqtincha o'chiring.

7.2 Hammasini bir kunda yoqish

Yuzlab xato — hammasi ! bilan "tuzatiladi". Tuzatish: bayroqma-bayroq, buyruq qatorida o'lchab.

7.3 noUncheckedIndexedAccess dan keyin ! ko'payishi

list[i]! — himoya yo'q. Tuzatish: const x = list[i]; if (x === undefined) …, yoki for...of / at() / find().

7.4 exactOptionalPropertyTypes va { a: undefined }

TS2375 / TS2379. Tuzatish: kalitni umuman yozmang (...(phone ? { phone } : {})) yoki turga | undefined qo'shing.

7.5 alwaysStrict: false

TS5108 — TypeScript 7 da olib tashlangan. Tuzatish: qatorni o'chiring.

8. Mashqlar

1-mashq (oson): Kod — bayroq

Har xato kodiga uni beradigan bayroqni yozing (bitta so'z):

  1. TS7030: Not all code paths return a value. —
  2. TS18046: 'e' is of type 'unknown'. —
  3. TS4114: This member must have an 'override' modifier… —
Yechim

noImplicitReturns — hamma yo'llar return qilmaydi. useUnknownInCatchVariables — strict ichidagi bayroq, catch (e) ni unknown qiladi. noImplicitOverride — ota-klass metodini almashtirishda override talab qiladi.

2-mashq (o'rta): Qat'iy sozlamada tuzating

Bu kod noUncheckedIndexedAccess bilan bitta xato beradi. Lekin unda yana bitta yashirin muammo bor: funksiya natija turi yozilmagan. ! va as ishlatmasdan tuzating, natija turini number qiling va yo'q taom uchun RangeError tashlang:

ts
// @ts-options: {"noUncheckedIndexedAccess": true}
type Size = "kichik" | "katta";
const PRICES: Record<string, number> = { osh: 35000, manti: 30000 };

function priceOf(dish: string, size: Size) {
  const base = PRICES[dish];
  switch (size) {
    case "kichik":
      return base * 0.7;
    case "katta":
      return base;
  }
}

Kompilyator:

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

TypeScript aytyapti: "base undefined bo'lishi mumkin" — PRICES[dish] da bunday kalit bo'lmasligi mumkin.

Yechim
ts
// @ts-options: {"noUncheckedIndexedAccess": true}
type Size = "kichik" | "katta";
const PRICES: Record<string, number> = { osh: 35000, manti: 30000 };

function priceOf(dish: string, size: Size): number {
  const base = PRICES[dish];
  if (base === undefined) {
    throw new RangeError(`Menyuda yo'q: ${dish}`);
  }
  switch (size) {
    case "kichik":
      return Math.round(base * 0.7);
    case "katta":
      return base;
  }
}

console.log(priceOf("osh", "kichik")); // 24500
console.log(priceOf("manti", "katta")); // 30000
  • base — number | undefined: if bilan toraytirdik, yo'q taom — RangeError.
  • Natija turi number yozilgach, switch ikkala Size ni qamraydi — kompilyator hamma yo'llar qaytishini ko'radi (to'liqlik tekshiruvi). Size ga uchinchi o'lcham qo'shilsa, tsc "hamma yo'l qaytarmaydi" deb ogohlantiradi.
  • Yashirin muammo: asl kodda natija turi chiqarilgan edi — number | undefined (katta shoxida base qaytgan). Chaqiruvchi har safar undefined ni tekshirishga majbur bo'lardi. Xatoni manbada — funksiya ichida — to'xtatish yaxshiroq.

3-mashq: Vazifalar qadami — strict oilasi

strict vazifalar da 12/39 dan beri yoqiq. Endi unga kirmaydigan bayroqlarni qo'shamiz — avval har birining narxini o'lchab.

  • Branch: chore/strict-bayroqlar
  • Commit: chore: strict oilasi — noUncheckedIndexedAccess va boshqalar, tanasi: qidiruv.ts: indeks tekshiruvi (2 xato)
  1. Har bayroqni alohida o'lchang: npx tsc --noEmit --<bayroq> (sakkiz bayroq: noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noUnusedLocals, noUnusedParameters, noPropertyAccessFromIndexSignature).
  2. Xato bergan haqiqiy joylarni tuzating.
  3. Foydali bayroqlarni tsconfig.json ga yozing (izoh bilan — nega).
  4. npm run build, npm test, npm run tip, npm run lint, npm run format:check.
Yechim

O'lchov (TypeScript 7.0.2, o'sha paytdagi .ts va // @ts-check li modullar):

Bayroq Xato
noUncheckedIndexedAccess 2
exactOptionalPropertyTypes 0
noImplicitOverride 0
noImplicitReturns 0
noFallthroughCasesInSwitch 0
noUnusedLocals / noUnusedParameters 0 / 0
noPropertyAccessFromIndexSignature 13 — hammasi paket.js dagi xom.versiya kabi Record ga nuqta bilan murojaat

Biz o'lchovni oldingi qadam holatida (holatlar/26) qayta takrorladik — raqamlar aynan shunday chiqdi. Olti bayroq — nol: kod ularning talablariga allaqachon javob beradi, ularni yoqish bepul va kelajakdagi xatodan himoya. noPropertyAccessFromIndexSignature — 13 ta, lekin hammasi uslub: yoqilmadi.

Ikki haqiqiy xato:

text
assets/js/qidiruv.ts(91,18): error TS2532: Object is possibly 'undefined'.
assets/js/qidiruv.ts(91,34): error TS2532: Object is possibly 'undefined'.

"Obyekt undefined bo'lishi mumkin". 91-qator — qidiruvda topilgan bo'lakni asl matnda belgilash (moslar funksiyasi):

ts
// Oldin
natija.push([joylar[joy][0], joylar[oxiri - 1][1]]);

joylar[joy] va joylar[oxiri - 1] — bayroq bilan [number, number] | undefined. Mantiqan ular doim bor (moslik matn ichida topilgan). Lekin kompilyator buni bilmaydi:

ts
// Keyin
// joylar toza bilan bir uzunlikda, moslik toza ichida — ikkalasi
// ham bor. noUncheckedIndexedAccess buni bilmaydi: massiv[i] turi
// T | undefined. "!" o'rniga tekshiruv — invariant buzilsa,
// belgilash to'xtaydi, sahifa yiqilmaydi
const birinchi = joylar[joy];
const oxirgi = joylar[oxiri - 1];
if (birinchi === undefined || oxirgi === undefined) {
  break;
}
natija.push([birinchi[0], oxirgi[1]]);

Nega ! emas? joylar[joy]![0] qisqaroq, lekin «TypeScript ushlamaydigan tuzoq» bo'limidagidek: kelajakda normalShakl o'zgarib, invariant buzilsa — TypeError va butun ro'yxat chizilmay qoladi. break bilan esa eng yomon holatda belgilash to'xtaydi, xolos. Invariant — "kodning shu joyida doim rost bo'lishi kerak bo'lgan shart"; izoh aynan uni yozib qo'yadi.

tsconfig.json (qo'shilgan qatorlar):

jsonc
    // strict'ga kirmaydigan, lekin xato ushlaydigan bayroqlar (15/#34):
    // massiv[i] va obyekt[kalit] — T | undefined
    "noUncheckedIndexedAccess": true,
    // { a?: string } ga a: undefined yozib bo'lmaydi — faqat tushirib
    "exactOptionalPropertyTypes": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,

Qolgan JavaScript: hali .ts ga o'tmagan modullarni checkJs bilan (to'liq bayroqlar bilan) o'lchadik — 221 xato: asosiy.js 120, render.js 84, tema-tanlash.js 12, olchov.js 5. Ular TypeScript va DOM va JavaScript'dan TypeScript'ga ko'chish qadamlarida tuzatiladi — endi qat'iy bayroqlar bilan.

Tekshiruv: npm run build — exit 0 (dist/: 29 fayl), npm test — 137/137, tip, lint, format:check — toza. Brauzer tekshiruvi (dist/, Chrome 154): birinchi urinishda dialog qadamida TimeoutError: Waiting failed: 5000ms, qayta ishga tushirishda — 159/159. O'zgargan kod faqat qidiruv.ts dagi indeks tekshiruvi edi; yiqilish tarmoq/vaqt bilan bog'liq beqarorlik bo'lib chiqdi (e2e kutish vaqti keyin 10 s ga oshirildi). Lighthouse — 98 / 100 / 100 / 100.

Commit va PR:

bash
git switch -c chore/strict-bayroqlar
for b in noUncheckedIndexedAccess exactOptionalPropertyTypes \
  noImplicitOverride noImplicitReturns noFallthroughCasesInSwitch \
  noUnusedLocals noUnusedParameters noPropertyAccessFromIndexSignature
do
  echo "$b: $(npx tsc --noEmit --$b | grep -c 'error TS')"
done
# qidiruv.ts va tsconfig.json tahrirlangach:
npm run build && npm test && npm run tip
npm run lint && npm run format:check
git add tsconfig.json assets/js/qidiruv.ts
git commit -m "chore: strict oilasi — noUncheckedIndexedAccess va boshqalar" \
  -m "qidiruv.ts: indeks tekshiruvi (2 xato)"
git push -u origin chore/strict-bayroqlar
gh pr create --fill
gh pr merge --merge

Shell'dagi for sikli sakkiz bayroqni birma-bir sinaydi; grep -c xato qatorlarini sanaydi. Commit sarlavhasi — 62 belgi. Diff: 3 fayl, +21 −2.

XATOLAR.md ga qo'shing: TS2564, TS2683, TS18046, TS2375, TS4114, TS7030, TS7029, TS6133, TS4111, TS2532 — har biri qaysi bayroqdan.

9. Real ishda

  • Yangi loyihalar — strict va tsc --init dagi ikki qat'iy bayroq bilan boshlanadi. Kutubxonalar (type-fest, Zod) va katta kompaniyalarning ochiq loyihalari ko'pincha yana noImplicitOverride, noFallthroughCasesInSwitch ni qo'shadi.
  • Eski loyihalar — strict: false va yuzlab yashirin xato. Ko'chish: bayroqma-bayroq, buyruq qatorida o'lchab, eng qimmatini (strictNullChecks) oxirga qoldirib. Ba'zi jamoalar buni fayl-fayl qiladi.
  • Kod ko'rib chiqishda "! nega kerak?" — eng ko'p uchraydigan savollardan. Javob izohda bo'lishi kerak.
  • Intervyu: "strict nimalarni yoqadi?", "noUncheckedIndexedAccess ning foydasi va narxi?", "exactOptionalPropertyTypes nima farq qiladi?" — tajribali TypeScript dasturchisidan kutiladigan savollar.

Xulosa

  • strict — sakkiz bayroq: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables, strictBuiltinIteratorReturn (+ doim yoqiq alwaysStrict). TypeScript 6/7 da sukut bo'yicha yoqiq.
  • strict dan tashqarida: noUncheckedIndexedAccess, exactOptionalPropertyTypes (tsc --init ularni yoqadi), noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noUnused*; uslub uchun — noPropertyAccessFromIndexSignature.
  • Bayroqni yoqishdan oldin narxini o'lchang: npx tsc --noEmit --<bayroq>.
  • ! va as har qanday bayroqni chetlab o'tadi — ularni izohsiz ishlatmang.
  • vazifalar: sakkiz bayroq o'lchandi, yettitasi yoqildi, 2 haqiqiy xato ! siz tuzatildi.

Keyingi dars: Modullar TypeScript'da — import type, verbatimModuleSyntax, .ts kengaytmali importlar va nega vazifalar da "./sinxron.ts" deb yoziladi.

Manbalar

  • TSConfig Reference: Type Checking (strict va har bir bayroq) — typescriptlang.org/tsconfig#strict
  • Microsoft, "Announcing TypeScript 6.0", 2026-03-23 — devblogs.microsoft.com/typescript/announcing-typescript-6-0/
  • Microsoft, "Announcing TypeScript 7.0", 2026-07-08 — devblogs.microsoft.com/typescript/announcing-typescript-7-0/
  • TypeScript Release Notes 4.4 (exactOptionalPropertyTypes, useUnknownInCatchVariables), 4.1 (noUncheckedIndexedAccess), 4.3 (override), 5.6 (strictBuiltinIteratorReturn) — typescriptlang.org/docs/handbook/release-notes/
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript strict bayroqlari: strict ichida nima bor va undan tashqaridagi himoyalar — IlmHamroh