14-bo‘lim

Literal turlar va enum

Tur kengayishi, satisfies operatori, enum ning ish vaqtidagi izi va shablon literal turlari.

🕑 25 daqiqa o‘qish 📄 848 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Tur kengayishi
  2. Kengayish obyekt literalida ham bo'ladi
  3. satisfies operatori
  4. enum
  5. enum ning ikki qirrasi
  6. const enum
  7. enum o'rniga literal union
  8. Shablon literal turlari
  9. Xulosa

3-bobda const va let ning turlari boshqacha ekanini ko'rdik. Bu bobda o'sha hodisani - tur kengayishini - to'liq o'rganamiz, satisfies operatorini tanishtiramiz va enum ni literal union bilan solishtiramiz.

Tur kengayishi #

TS
const a = "Olma";
let b = "Olma";

const x: "Olma" = a;
const y: "Olma" = b;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/keng.ts(5,7): error TS2322: Type 'string' is not assignable to type
'"Olma"'.

a - "Olma" literali, b esa string. let qayta tayinlanishi mumkin, shuning uchun TypeScript turni kengaytiradi.

Kengayish obyekt literalida ham bo'ladi #

Bu esa allaqachon ko'rgan naqshimizni buzadi:

TS
type Naqd = { usul: "naqd"; miqdor: number };

const xom = { usul: "naqd", miqdor: 12000 };
const t: Naqd = xom;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/keng2.ts(4,7): error TS2322: Type '{ usul: string; miqdor: number; }'
is not assignable to type 'Naqd'.
  Types of property 'usul' are incompatible.
    Type 'string' is not assignable to type '"naqd"'.

xom const bo'lsa ham, uning maydonlari o'zgartirilishi mumkin (xom.usul = "karta"). Shuning uchun usul string ga kengaydi.

Uchta yechim bor:

TS
type Naqd = { usul: "naqd"; miqdor: number };

const a: Naqd = { usul: "naqd", miqdor: 12000 };
const b = { usul: "naqd" as const, miqdor: 25000 };
const c = { usul: "naqd", miqdor: 30000 } as const;

const t1: Naqd = a;
const t2: Naqd = b;
const t3: Naqd = c;

console.log(t1.miqdor, t2.miqdor, t3.miqdor);
Terminal
tsx src/keng3.ts
Natija
12000 25000 30000
YechimTa'siri
const a: Naqd = {...}Tur oldindan ma'lum - kengayish yo'q
usul: "naqd" as constFaqat bitta maydon qotadi
{...} as constBarcha maydonlar readonly va literal
Qaysi yozuvda tur kengayadi Yozuv Natijaviy tur Nega const a = "Olma" "Olma" qayta tayinlab bo'lmaydi let b = "Olma" string keyin boshqa satr berilishi mumkin const o = { u: "naqd" } { u: string } o.u = "karta" mumkin { u: "naqd" } as const { readonly u: "naqd" } o'zgartirish taqiqlangan Umumiy qoida Qiymat kelajakda o'zgarishi mumkin bo'lsa, TypeScript turni kengaytiradi. as const - "o'zgarmaydi" degan va'da, kengayish esa o'sha zahoti to'xtaydi.
Kengayish o'zgaruvchanlikdan kelib chiqadi, const kalit so'zidan emas

satisfies operatori #

Turni annotatsiya bilan berish bitta yon ta'sirga ega - o'zgaruvchi o'sha turga aylanadi:

TS
type Narxlar = Record<string, number>;

const narxlar: Narxlar = { olma: 12000, anor: 25000 };

console.log(narxlar.olma.toFixed(0));
console.log(narxlar.yoq.toFixed(0));
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/satis.ts 2>&1 | grep -oE "(^12000|TypeError.*)" | head -2
Natija
tsc: xato yo_q
12000
TypeError: Cannot read properties of undefined (reading 'toFixed')

narxlar endi Record<string, number> - unda istalgan kalit bor deb hisoblanadi. Aniq kalitlar haqidagi bilim yo'qoldi.

satisfies tekshiradi, lekin turni almashtirmaydi:

TS
type Narxlar = Record<string, number>;

const narxlar = {
  olma: 12000,
  anor: 25000,
} satisfies Narxlar;

console.log(narxlar.olma.toFixed(0));
console.log(narxlar.yoq);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/satis2.ts(9,21): error TS2339: Property 'yoq' does not exist on type
'{ olma: number; anor: number; }'.

Tekshiruv esa baribir ishlaydi:

TS
type Narxlar = Record<string, number>;

const narxlar = {
  olma: 12000,
  anor: "yigirma besh ming",
} satisfies Narxlar;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/satis3.ts(5,3): error TS2322: Type 'string' is not assignable to type
'number'.
: yoki satisfies - qaysi biri
MaqsadTanlov
Qiymat shu turga mos bo'lsinsatisfies
Qiymat aynan shu tur bo'lsin:
Keyin maydon qo'shiladi:
Aniq kalitlar saqlansinsatisfies

Sozlama obyektlari, marshrutlar jadvali, rang palitrasi - bularning hammasi uchun satisfies to'g'riroq: siz ham tekshiruvni olasiz, ham aniq bilimni yo'qotmaysiz.

enum #

TS
enum Daraja {
  Past,
  Orta,
  Yuqori,
}

console.log(Daraja.Orta);
console.log(Daraja[1]);
console.log(Object.keys(Daraja).join(","));
Terminal
tsx src/enum.ts
Natija
1
Orta
0,1,2,Past,Orta,Yuqori

Uchta narsa ko'rindi:

  • Daraja.Orta - 1, chunki raqamlar noldan boshlab beriladi;
  • Daraja[1] - "Orta", ya'ni teskari moslik bor;
  • kalitlar soni uchta emas, oltita.

Chunki enum ish vaqtida haqiqiy obyektga aylanadi:

TS
export enum Daraja {
  Past,
  Orta,
}
Terminal
tsc
echo "--- dist/enum2.js ---"
cat dist/enum2.js
Natija
--- dist/enum2.js ---
export var Daraja;
(function (Daraja) {
    Daraja[Daraja["Past"] = 0] = "Past";
    Daraja[Daraja["Orta"] = 1] = "Orta";
})(Daraja || (Daraja = {}));

Har bir a'zo ikki marta yoziladi - nomdan raqamga va raqamdan nomga.

Satrli enum da teskari moslik yo'q:

TS
enum Usul {
  Naqd = "naqd",
  Karta = "karta",
}

console.log(Usul.Naqd);
console.log(Object.keys(Usul).join(","));
Terminal
tsx src/enum3.ts
Natija
naqd
Naqd,Karta

enum ning ikki qirrasi #

Raqamli enum ilgari istalgan sonni qabul qilardi. Bu zamonaviy TypeScript da tuzatilgan:

TS
enum Daraja {
  Past,
  Orta,
  Yuqori,
}

const a: Daraja = 99;
const b: Daraja = Daraja.Past;
console.log(a, b);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/enum4.ts(7,7): error TS2322: Type '99' is not assignable to type
'Daraja'.

Satrli enum esa nominal - qiymati bir xil bo'lsa ham, oddiy satr unga mos kelmaydi:

TS
enum Usul {
  Naqd = "naqd",
  Karta = "karta",
}

function chop(u: Usul): string {
  return u;
}

console.log(chop(Usul.Naqd));
chop("naqd");
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/enum5.ts(11,6): error TS2345: Argument of type '"naqd"' is not
assignable to parameter of type 'Usul'.

Bu - butun tur tizimidagi ikkinchi nominal joy (birinchisi - 10-bobdagi private maydonli sinflar).

Amalda bu noqulay: serverdan "naqd" kelganda uni Usul.Naqd ga aylantirishga to'g'ri keladi.

const enum #

TS
const enum Yonalish {
  Yuqori = 1,
  Past,
}

export const y = Yonalish.Yuqori;
console.log(y, Yonalish.Past);
Terminal
tsc
echo "--- dist/cenum.js ---"
cat dist/cenum.js
echo "--- isolatedModules bilan ---"
tsc --noEmit --isolatedModules 2>&1 | fold -sw 74
Natija
--- dist/cenum.js ---
export const y = 1 /* Yonalish.Yuqori */;
console.log(y, 2 /* Yonalish.Past */);
--- isolatedModules bilan ---

const enum hech qanday obyekt qoldirmadi - qiymatlar o'rniga to'g'ridan-to'g'ri 1 va 2 yozildi. tsc esa --isolatedModules bilan ham hech narsa demadi.

const enum dan voz keching

Yuqoridagi jimlik xavfsizlikni anglatmaydi.

Inlaytirish uchun kompilyator enum ning qiymatlarini bilishi kerak. esbuild, swc va Babel esa har bir faylni alohida o'giradi - ular qo'shni fayldagi const enum ni ko'rmaydi.

Natijada:

  • Vite yoki esbuild ishlatilsa, boshqa fayldan import qilingan const enum to'g'ri ishlamaydi;
  • e'lon fayli (.d.ts) tarqatadigan kutubxonada u butunlay ishlatib bo'lmaydi.

Shuning uchun TypeScript hujjati ham, ko'p uslub qo'llanmalari ham const enum ni tavsiya qilmaydi.

enum o'rniga literal union #

TS
const USULLAR = ["naqd", "karta"] as const;
type Usul = (typeof USULLAR)[number];

function chop(u: Usul): string {
  return "usul: " + u;
}

console.log(chop("naqd"));
for (const u of USULLAR) console.log(chop(u));
Terminal
tsx src/union.ts
Natija
usul: naqd
usul: naqd
usul: karta

chop("naqd") to'g'ridan-to'g'ri ishladi - hech qanday aylantirish kerak bo'lmadi.

enum Usulas const + union
Ish vaqtidagi kodBorYo'q
Satr bilan mosYo'qHa
Ro'yxat bo'ylab aylanishObject.valuesTo'g'ridan-to'g'ri
JSON bilan ishlashAylantirish kerakTo'g'ridan-to'g'ri
Teskari moslikBorYo'q

Teskari moslik chindan kerak bo'lgan kam sonli holatlardan tashqari, ikkinchi ustun deyarli har doim afzal.

Shablon literal turlari #

TS
type Rang = "qizil" | "yashil";
type Olcham = "kichik" | "katta";
type Sinf = `${Rang}-${Olcham}`;

const a: Sinf = "qizil-katta";
const b: Sinf = "yashil-kichik";

console.log(a, b);
Terminal
tsx src/shablon.ts
Natija
qizil-katta yashil-kichik
TS
type Rang = "qizil" | "yashil";
type Olcham = "kichik" | "katta";
type Sinf = `${Rang}-${Olcham}`;

const x: Sinf = "qizil-orta";
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/shablon2.ts(5,7): error TS2322: Type '"qizil-orta"' is not assignable
to type '"qizil-kichik" | "qizil-katta" | "yashil-kichik" |
"yashil-katta"'.

Xato xabari eng qiziq qismini ko'rsatdi: TypeScript ikkita ikki a'zoli uniondan to'rtta birikma yasadi.

13-bobdagi Capitalize bilan birga:

TS
type Hodisa = "bosildi" | "yopildi";
type Ishlovchi = `on${Capitalize<Hodisa>}`;

const ishlovchilar: Record<Ishlovchi, () => void> = {
  onBosildi: () => console.log("bosildi"),
  onYopildi: () => console.log("yopildi"),
};

ishlovchilar.onBosildi();
ishlovchilar.onYopildi();
Terminal
tsx src/shablon3.ts
Natija
bosildi
yopildi
Birikmalar soni ko'payib ketadi

Shablon literal turi barcha birikmalarni yaratadi. Uchta 10 a'zoli union - bu 1000 ta variant.

TypeScript da bu chegara 100 000 atrofida; undan oshsa TS2590 xatosi chiqadi va tahrirlovchi sekinlashadi.

Uchtadan ko'p union ni shablonda birlashtirishdan oldin o'ylab ko'ring.

Xulosa #

  • Tur kengayishi o'zgaruvchanlikdan kelib chiqadi: let va obyekt maydonlari kengayadi, const esa yo'q.
  • Obyekt literalining maydoni const ichida ham kengayadi - chunki maydonni keyin o'zgartirish mumkin.
  • Uchta yechim: o'zgaruvchiga tur yozish, "qiymat" as const, yoki butun obyektga as const.
  • Annotatsiya (: Tur) qiymatning turini almashtiradi va aniq kalitlar haqidagi bilimni yo'qotadi.
  • satisfies tekshiradi, lekin turni almashtirmaydi - sozlama obyektlari uchun eng mos tanlov.
  • Raqamli enum teskari moslikka ega va kalitlari soni ikki barobar ko'p.
  • enum kompilyatsiyadan keyin ham kod qoldiradi - literal union esa qoldirmaydi.
  • Satrli enum nominal: "naqd" qiymati Usul.Naqd ga mos kelmaydi.
  • const enum inlaytiriladi, lekin transpilyatsiya vositalari bilan ishlamaydi - undan voz keching.
  • as const massiv + (typeof X)[number] - enum ning zamonaviy o'rnini bosuvchisi.
  • Shablon literal turlari union larni ko'paytiradi; ular bilan ehtiyot bo'ling.
Amaliy topshiriq
  1. const va let bilan bir xil satr yozib, turlarini solishtiring.
  2. Obyekt literalini ajratuvchi maydonli turga berib, kengayish xatosini oling.
  3. Uni uch xil usulda tuzating.
  4. Record<string, number> ga annotatsiya bilan qiymat berib, mavjud bo'lmagan kalitni o'qing va dasturni yiqiting.
  5. Xuddi shuni satisfies bilan yozib, kompilyatsiyada tutilishini ko'ring.
  6. Raqamli enum yozib, Object.keys natijasini sanang.
  7. tsc chiqishida enum qanday kodga aylanganini o'qing.
  8. Satrli enum kutadigan funksiyaga oddiy satr berib, TS2345 ni oling.
  9. O'sha enum ni as const union ga almashtirib, muammo yo'qolishini tasdiqlang.
  10. Ikkita uniondan shablon literal turi yasab, nechta variant hosil bo'lganini xato xabaridan o'qing.

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.