15-bo‘lim

any, unknown va never

Uchta maxsus tur, JSON.parse xavfi, bo'sh obyekt turining kutilmagan kengligi va ularni to'g'ri tanlash.

🕑 27 daqiqa o‘qish 📄 858 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. any zanjir bo'ylab tarqaladi
  2. unknown darhol to'xtatadi
  3. Tayinlash yo'nalishi
  4. JSON.parse - any ning eng keng tarqalgan manbai
  5. catch dagi e
  6. Bo'sh obyekt turi {}
  7. never unionda yo'qoladi
  8. void, undefined va never
  9. any[] va unknown[]
  10. Xulosa

Tur tizimining chekkalarida uchta maxsus tur turadi:

TurMa'nosi
any"Tekshirishni to'xtat"
unknown"Hali bilmayman"
never"Bunday qiymat bo'lmaydi"

Ular oson chalkashtiriladi, holbuki farqi juda katta.

any zanjir bo'ylab tarqaladi #

TS
const javob: any = { nomi: "Olma" };

const nomi = javob.nomi;
const uzunlik = nomi.length;
const yakun = uzunlik.toUpperCase();

console.log(yakun);
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/any.ts 2>&1 | grep -oE "TypeError.*" | head -1
Natija
tsc: xato yo_q
TypeError: uzunlik.toUpperCase is not a function

Uchta o'zgaruvchi, uchtasi ham any. Hech qaysisiga tur yozilmagan, lekin hech qaysisi tekshirilmadi ham.

any bitta o'zgaruvchini emas, undan kelib chiqadigan butun zanjirni himoyasiz qoldiradi.

Bitta istisno bor - arifmetika:

TS
const xom: any = "12000";

const narx = xom * 2;
const yakun = narx.toUpperCase();
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/any2.ts(4,20): error TS2339: Property 'toUpperCase' does not exist on
type 'number'.

any * 2 - number, chunki * boshqa natija berolmaydi. Shu joyda zanjir uzildi va tekshiruv qaytadi.

unknown darhol to'xtatadi #

TS
const xom: unknown = "12000";
console.log(xom.length);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/unknown.ts(2,13): error TS18046: 'xom' is of type 'unknown'.

unknown ham istalgan qiymatni qabul qiladi - lekin uni ishlatishdan oldin tekshirish talab qilinadi:

TS
function uzunlik(x: unknown): number {
  if (typeof x === "string") return x.length;
  if (Array.isArray(x)) return x.length;
  return 0;
}

console.log(uzunlik("Olma"), uzunlik([1, 2, 3]), uzunlik(42));
Terminal
tsx src/unknown2.ts
Natija
4 3 0

Tayinlash yo'nalishi #

TS
let a: any = 1;
let u: unknown = 1;
let s: string;

s = a;
u = a;
a = u;
s = u;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/yonalish.ts(8,1): error TS2322: Type 'unknown' is not assignable to
type 'string'.

To'rtta tayinlashdan faqat bittasi xato berdi:

Yo'nalishRuxsat
any → istalgan turHa
anyunknownHa
unknownanyHa
unknown → aniq turYo'q

Aynan shu qator unknown ni any dan ajratib turadi.

Uchta maxsus tur any hamma qiymatni oladi hamma joyga beriladi Tekshiruv butunlay o'chiriladi Zanjir bo'ylab tarqaladi Faqat eski kodni ko'chirishda vaqtincha unknown hamma qiymatni oladi hech qayerga berilmaydi Ishlatishdan oldin tekshirish shart Zanjirni to'xtatadi Tashqi ma'lumot uchun to'g'ri tanlov never hech qiymatni olmaydi hamma joyga beriladi Bunday qiymat mavjud emas To'liqlik tekshiruvi Ziddiyatli kesishma Qaytmaydigan funksiya Unionda: string | never = string (never yo'qoladi) string | unknown = unknown (unknown yutadi) never - eng tor tur, unknown - eng keng. any esa ikkalasidek ham o'zini tutadi.
any - qulf ochiq qoldirilgan eshik, unknown - qulflangan, never - eshikning o'zi yo'q

JSON.parse - any ning eng keng tarqalgan manbai #

TS
const javob = JSON.parse('{"nomi":"Olma"}');
console.log(javob.narx.toFixed(2));
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/json.ts 2>&1 | grep -oE "TypeError.*" | head -1
Natija
tsc: xato yo_q
TypeError: Cannot read properties of undefined (reading 'toFixed')

JSON.parse any qaytaradi - boshqa ilojisi yo'q, chunki satrning ichida nima borligini kompilyator bilolmaydi.

Muammo shundaki, any jimgina keladi. Yechim - uni darhol unknown ga aylantirib, tekshirish:

TS
type Mahsulot = { nomi: string; narx: number };

function mahsulotmi(x: unknown): x is Mahsulot {
  if (typeof x !== "object" || x === null) return false;
  const o = x as Record<string, unknown>;
  return typeof o.nomi === "string" && typeof o.narx === "number";
}

const a: unknown = JSON.parse('{"nomi":"Olma"}');
const b: unknown = JSON.parse('{"nomi":"Anor","narx":25000}');

console.log(mahsulotmi(a) ? a.narx : "notogri malumot");
console.log(mahsulotmi(b) ? b.narx : "notogri malumot");
Terminal
tsx src/json2.ts
Natija
notogri malumot
25000

Birinchi javobda narx yo'q edi - va u ish vaqtida, to'g'ri joyda tutildi.

Chegarada tekshiring

Tashqi ma'lumot kiradigan har bir joyda - fetch, JSON.parse, localStorage, forma, process.env - turni unknown deb belgilang va bir marta tekshiring.

Katta loyihada buni qo'lda yozish zerikarli. Tayyor yechimlar:

KutubxonaYondashuv
ZodSxema yozasiz, tur o'zi chiqadi
ValibotZod ga o'xshash, kichikroq
TypeBoxJSON Schema bilan mos

Ular 7-bobdagi tur predikatini avtomatik yasaydi.

catch dagi e #

TS
try {
  throw new Error("xato yuz berdi");
} catch (e) {
  console.log(e.message);
}
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/catch.ts(4,15): error TS18046: 'e' is of type 'unknown'.

JavaScript da throw istalgan qiymatni tashlashi mumkin - satr, son, obyekt. Shuning uchun e - unknown:

TS
function xabar(e: unknown): string {
  if (e instanceof Error) return e.message;
  return String(e);
}

try {
  throw new Error("xato yuz berdi");
} catch (e) {
  console.log(typeof e, "|", xabar(e));
}

try {
  throw "oddiy satr";
} catch (e) {
  console.log(typeof e, "|", xabar(e));
}
Terminal
tsx src/catch2.ts
Natija
object | xato yuz berdi
string | oddiy satr

Ikkinchi holat ko'rsatib turibdi: catch ga har doim Error kelmaydi.

Bo'sh obyekt turi {} #

Bu - eng ko'p chalkashtiriladigan tur:

TS
const a: {} = "Olma";
const b: {} = 12000;
const c: {} = true;
const d: {} = { nomi: "Olma" };
const e: {} = null;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/bosh.ts(5,7): error TS2322: Type 'null' is not assignable to type
'{}'.

Satr ham, son ham, mantiqiy qiymat ham o'tdi. {} "bo'sh obyekt" degani emas - u "null va undefined dan boshqa hamma narsa" degani.

Va undan hech qanday foyda yo'q:

TS
const a: {} = "Olma";
console.log(a.length);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/bosh2.ts(2,15): error TS2339: Property 'length' does not exist on
type '{}'.

object esa haqiqatan obyektlarni talab qiladi:

TS
const a: object = { nomi: "Olma" };
const b: object = [1, 2];
const c: object = () => 1;
const d: object = "Olma";
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/obyekt.ts(4,7): error TS2322: Type 'string' is not assignable to type
'object'.

Massiv va funksiya ham obyekt - faqat satr o'tmadi.

TurNimani qabul qiladi
{}null va undefined dan boshqa hammasi
objectObyekt, massiv, funksiya
Record<string, unknown>Kalitli obyekt
unknownHamma narsa

Amalda: "istalgan qiymat" uchun unknown, "kalitli obyekt" uchun Record<string, unknown> yozing. {} va Object ni esa umuman ishlatmang.

never unionda yo'qoladi #

TS
type A = string | never;
type B = string | unknown;

const a: A = "Olma";
const b: B = 12000;

console.log(a, b);
Terminal
tsx src/union.ts
Natija
Olma 12000

B ga son berildi - demak string | unknown aslida unknown ga teng. A ni tekshiramiz:

TS
type A = string | never;

const c: A = 42;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/union2.ts(3,7): error TS2322: Type 'number' is not assignable to type
'string'.

Xato xabari A ni string deb atadi - never izsiz yo'qolgan.

void, undefined va never #

TS
function xatoBer(m: string): never {
  throw new Error(m);
}

function hechnima(): void {}

function aniqmas(): undefined {
  return undefined;
}

console.log(typeof hechnima(), aniqmas());
console.log(typeof xatoBer);
Terminal
tsx src/void.ts
Natija
undefined undefined
function

Ish vaqtida uchalasi ham undefined bilan bog'liq, lekin turlar darajasida farq bor:

TS
const a: void = undefined;
const b: undefined = undefined;
const c: never = undefined;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/never.ts(3,7): error TS2322: Type 'undefined' is not assignable to
type 'never'.
TurMa'nosi
voidFunksiya tugaydi, natijaga qiziqilmaydi
undefinedAniq undefined qiymati
neverFunksiya tugamaydi yoki qiymat mavjud emas

any[] va unknown[] #

TS
const xom: any[] = [1, "ikki", true];

const birinchi = xom[0];
birinchi.qandaydirMetod();
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/massiv.ts 2>&1 | grep -oE "TypeError.*" | head -1
Natija
tsc: xato yo_q
TypeError: birinchi.qandaydirMetod is not a function
TS
const xom: unknown[] = [1, "ikki", true];

const birinchi = xom[0];
birinchi.qandaydirMetod();
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/massiv2.ts(4,1): error TS18046: 'birinchi' is of type 'unknown'.

Aralash massiv kerak bo'lsa, any[] emas, unknown[] yoki aniq union - (string | number)[] - yozing.

any qayerdan kelib qoladi

Siz yozmasangiz ham any paydo bo'ladi:

ManbaYechim
JSON.parseunknown ga o'tkazib tekshiring
Turlanmagan npm paketi@types/* yoki o'z e'loningiz (16-bob)
catch (e)strict da allaqachon unknown
Eski .js fayllarallowJs bilan asta ko'chiring (18-bob)
as anyDeyarli har doim keraksiz

tsc --noEmit --noImplicitAny bilan yashirin any larni topasiz, lekin ochiq yozilganlarini topa olmaysiz. Buning uchun ESLint ning no-explicit-any qoidasi kerak.

Xulosa #

  • any tekshiruvni o'chiradi va butun zanjir bo'ylab tarqaladi; faqat arifmetika uni to'xtatadi.
  • unknown ham hamma qiymatni qabul qiladi, lekin uni ishlatishdan oldin tekshirish majburiy.
  • unknown ni aniq turga berib bo'lmaydi - bu ikkalasining asosiy farqi.
  • JSON.parse any qaytaradi; natijani unknown deb belgilab, tur predikati bilan tekshiring.
  • Tashqi ma'lumot kiradigan har bir chegarada tekshiring; katta loyihada Zod kabi kutubxona qulay.
  • catch (e) da e - unknown, chunki JavaScript istalgan qiymatni tashlashi mumkin.
  • {} "bo'sh obyekt" emas - u null va undefined dan boshqa hamma narsani qabul qiladi va hech narsa bermaydi.
  • object obyekt, massiv va funksiyani qabul qiladi, primitivlarni esa yo'q.
  • Unionda never yo'qoladi, unknown esa qolgan hammasini yutadi.
  • void, undefined va never uchtasi uch xil narsa.
  • Aralash massiv uchun any[] emas, unknown[] yoki aniq union yozing.
Amaliy topshiriq
  1. any dan boshlanadigan uch bosqichli zanjir yozing va dasturni yiqiting.
  2. any ni arifmetikada ishlatib, tekshiruv qaytganini ko'ring.
  3. unknown ni to'g'ridan-to'g'ri ishlatib, TS18046 ni oling.
  4. typeof va Array.isArray bilan uni toraytiring.
  5. unknown ni string ga berib, TS2322 ni chaqiring.
  6. JSON.parse natijasini tekshirmasdan ishlatib, dasturni yiqiting.
  7. Tur predikati yozib, o'sha kodni xavfsiz qiling.
  8. catch (e) da e.message yozib, TS18046 ni oling, keyin instanceof bilan tuzating.
  9. {} turiga satr, son va null berib, qaysi biri o'tishini aniqlang.
  10. any[] va unknown[] ni solishtirib, farqni bir jumlada yozing.

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.