TypeScript enumlari uchun muqobillarni, jumladan const assertion va union type'larni o'rganing va optimal kodni saqlash hamda ishlash uchun ulardan qachon foydalanishni bilib oling.
TypeScript Enum Alternativlari: Const Assertions va Union Typesga Qarshi
TypeScript'ning enum — nomlangan konstantalar to'plamini aniqlash uchun kuchli xususiyatdir. Biroq, u har doim ham eng yaxshi tanlov emas. Ushbu maqola enumlarga muqobillarni, xususan, const assertion va union types'ni ko'rib chiqadi va har birini optimal kod sifati, saqlanishi va ishlashi uchun qachon ishlatish bo'yicha ko'rsatmalar beradi. Biz har bir yondashuvning nozik tomonlarini o'rganib chiqamiz, amaliy misollar keltiramiz va umumiy tashvishlarni hal qilamiz.
TypeScript Enumlarni Tushunish
Muqobillarga sho'ng'ishdan oldin, TypeScript enumlarni tezda ko'rib chiqaylik. Enum — nomlangan raqamli konstantalar to'plamini aniqlash usulidir. Odatiy bo'lib, birinchi enum a'zosiga 0 qiymati beriladi va keyingi a'zolar 1 ga oshiriladi.
enum Status {
Pending,
InProgress,
Completed,
Rejected,
}
const currentStatus: Status = Status.InProgress; // currentStatus will be 1
Enum a'zolariga qiymatlarni aniq belgilashingiz ham mumkin:
enum HTTPStatus {
OK = 200,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
}
const serverResponse: HTTPStatus = HTTPStatus.OK; // serverResponse will be 200
Enumlarning Afzalliklari
- O'qishga Qulaylik: Enumlar raqamli konstantalar uchun ma'noli nomlar berish orqali kodning o'qishga qulayligini oshiradi.
- Turi Xavfsizligi: Ular qiymatlarni belgilangan enum a'zolari bilan cheklash orqali turi xavfsizligini ta'minlaydi.
- Avtomatik Tugallash: IDE'lar enum a'zolari uchun avtomatik tugallash takliflarini taqdim etadi, bu xatolarni kamaytiradi.
Enumlarning Kamchiliklari
- Runtime Xarajatlar: Enumlar JavaScript obyektlariga kompilyatsiya qilinadi, bu esa runtime xarajatlarni keltirib chiqarishi mumkin, ayniqsa katta ilovalarda.
- O'zgaruvchanlik: Enumlar odatiy bo'lib o'zgaruvchandir. TypeScript mutatsiyani oldini olish uchun
const enumni taqdim etsa-da, uning cheklovlari bor. - Teskari Xaritalash: Raqamli enumlar teskari xaritalashni yaratadi (masalan,
Status[1]"InProgress"ni qaytaradi), bu ko'pincha keraksizdir va paket hajmini oshirishi mumkin.
Alternativ 1: Const Assertions
Const assertionlar o'zgarmas, faqat o'qiladigan ma'lumotlar tuzilmalarini yaratish usulini taqdim etadi. Ular ko'p holatlarda enumlarga muqobil sifatida ishlatilishi mumkin, ayniqsa sizga oddiy string yoki raqamli konstantalar to'plami kerak bo'lganda.
const Status = {
Pending: 'pending',
InProgress: 'in_progress',
Completed: 'completed',
Rejected: 'rejected',
} as const;
// Typescript infers the following type:
// {
// readonly Pending: "pending";
// readonly InProgress: "in_progress";
// readonly Completed: "completed";
// readonly Rejected: "rejected";
// }
type StatusType = typeof Status[keyof typeof Status]; // 'pending' | 'in_progress' | 'completed' | 'rejected'
function processStatus(status: StatusType) {
console.log(`Processing status: ${status}`);
}
processStatus(Status.InProgress); // Valid
// processStatus('invalid'); // Error: Argument of type '"invalid"' is not assignable to parameter of type 'StatusType'.
Ushbu misolda biz string qiymatlarga ega oddiy JavaScript obyektini aniqlaymiz. The as const assertion TypeScript'ga ushbu obyektni faqat o'qiladigan deb hisoblashni va uning xususiyatlari uchun eng aniq turlarni inferatsiya qilishni aytadi. Keyin biz kalitlardan union type'ni ajratib olamiz. Bu yondashuv bir qator afzalliklarni taqdim etadi:
Const Assertions Afzalliklari
- O'zgarmaslik: Const assertionlar o'zgarmas ma'lumotlar tuzilmalarini yaratadi, tasodifiy o'zgarishlarning oldini oladi.
- Runtime Xarajatsiz: Ular oddiy JavaScript obyektlari bo'lib, enumlarga bog'liq runtime xarajatlari yo'q.
- Turi Xavfsizligi: Ular qiymatlarni belgilangan konstantalar bilan cheklash orqali kuchli turi xavfsizligini ta'minlaydi.
- Tree-shaking'ga mos: Zamonaviy bundlerlar ishlatilmaydigan qiymatlarni osongina tree-shake qila oladi, bu esa paket hajmini kamaytiradi.
Const Assertions Uchun Mulohazalar
- Ko'proq so'zli: Belgilash va tip berish enumlarga qaraganda biroz ko'proq so'zli bo'lishi mumkin, ayniqsa oddiy holatlarda.
- Teskari Xaritalash Yo'q: Ular teskari xaritalashni ta'minlamaydi, ammo bu ko'pincha kamchilikdan ko'ra afzallikdir.
Alternativ 2: Union Types
Union type'lar bir nechta mumkin bo'lgan turlardan birini saqlashi mumkin bo'lgan o'zgaruvchini aniqlashga imkon beradi. Ular obyektlarsiz ruxsat etilgan qiymatlarni aniqlashning yanada to'g'ridan-to'g'ri usuli bo'lib, enum yoki const assertionning kalit-qiymat munosabatlari kerak bo'lmaganda foydalidir.
type Status = 'pending' | 'in_progress' | 'completed' | 'rejected';
function processStatus(status: Status) {
console.log(`Processing status: ${status}`);
}
processStatus('in_progress'); // Valid
// processStatus('invalid'); // Error: Argument of type '"invalid"' is not assignable to parameter of type 'Status'.
Bu ruxsat etilgan qiymatlar to'plamini aniqlashning qisqa va turi xavfsiz usulidir.
Union Types Afzalliklari
- Qisqalik: Union type'lar eng qisqa yondashuv bo'lib, ayniqsa oddiy string yoki raqamli konstantalar to'plamlari uchun.
- Turi Xavfsizligi: Ular qiymatlarni belgilangan variantlar bilan cheklash orqali kuchli turi xavfsizligini ta'minlaydi.
- Runtime Xarajatsiz: Union type'lar faqat kompilyatsiya vaqtida mavjud bo'lib, runtime ko'rinishiga ega emas.
Union Types Uchun Mulohazalar
- Kalit-Qiymat Bog'lanishi Yo'q: Ular enums yoki const assertionlar kabi kalit-qiymat munosabatini ta'minlamaydi. Bu shuni anglatadiki, siz qiymatni uning nomi bo'yicha osongina qidirib topa olmaysiz.
- String Literal Qaytarish: Agar bir xil qiymatlar to'plamini bir nechta joyda ishlatsangiz, string literallarni takrorlashga to'g'ri kelishi mumkin. Bu umumiy
typeta'rifi bilan yumshatilishi mumkin.
Qaysi Birini Qachon Ishlatish Kerak?
Eng yaxshi yondashuv sizning o'ziga xos ehtiyojlaringiz va ustuvorliklaringizga bog'liq. Bu yerda sizga tanlashda yordam beradigan qo'llanma:
- Enumlardan qachon foydalanish kerak:
- Sizga bilvosita ortib boruvchi oddiy raqamli konstantalar to'plami kerak bo'lganda.
- Sizga teskari xaritalash kerak bo'lganda (garchi bu kamdan-kam hollarda zarur bo'lsa ham).
- Agar siz enumlardan keng foydalanadigan eski kod bilan ishlayotgan bo'lsangiz va uni o'zgartirishga shoshilinch ehtiyojingiz bo'lmasa.
- Const Assertionlardan qachon foydalanish kerak:
- Sizga o'zgarmas bo'lishi kerak bo'lgan string yoki raqamli konstantalar to'plami kerak bo'lganda.
- Sizga kalit-qiymat munosabati kerak bo'lganda va runtime xarajatlardan qochmoqchi bo'lsangiz.
- Tree-shaking va paket hajmi muhim e'tiborga olinishi kerak bo'lganda.
- Union Type'lardan qachon foydalanish kerak:
- Sizga ruxsat etilgan qiymatlar to'plamini aniqlashning oddiy va qisqa usuli kerak bo'lganda.
- Sizga kalit-qiymat munosabati kerak bo'lmaganda.
- Ishlash va paket hajmi juda muhim bo'lganda.
Misol Stsenariy: Foydalanuvchi Rollarini Belgilash
Keling, dasturda foydalanuvchi rollarini belgilash kerak bo'lgan stsenariyni ko'rib chiqaylik. Sizda "Admin", "Editor" va "Viewer" kabi rollar bo'lishi mumkin.
Enumlardan Foydalanish:
enum UserRole {
Admin,
Editor,
Viewer,
}
function authorize(role: UserRole) {
// ...
}
Const Assertionlardan Foydalanish:
const UserRole = {
Admin: 'admin',
Editor: 'editor',
Viewer: 'viewer',
} as const;
type UserRoleType = typeof UserRole[keyof typeof UserRole];
function authorize(role: UserRoleType) {
// ...
}
Union Type'lardan Foydalanish:
type UserRole = 'admin' | 'editor' | 'viewer';
function authorize(role: UserRole) {
// ...
}
Ushbu stsenariyda union type'lar eng qisqa va samarali yechimni taklif qiladi. Agar siz kalit-qiymat munosabatini afzal ko'rsangiz, masalan, har bir rolning tavsifini qidirish uchun, const assertionlar yaxshi muqobil hisoblanadi. Enamlar odatda raqamli qiymatlar yoki teskari xaritalash uchun o'ziga xos ehtiyojingiz bo'lmasa, bu yerda tavsiya etilmaydi.
Misol Stsenariy: API So'rov Holati Kodlarini Belgilash
Keling, API so'rov holati kodlarini belgilash kerak bo'lgan stsenariyni ko'rib chiqaylik. Sizda 200 (OK), 400 (Bad Request), 401 (Unauthorized) va 500 (Internal Server Error) kabi kodlar bo'lishi mumkin.
Enumlardan Foydalanish:
enum StatusCode {
OK = 200,
BadRequest = 400,
Unauthorized = 401,
InternalServerError = 500
}
function processStatus(code: StatusCode) {
// ...
}
Const Assertionlardan Foydalanish:
const StatusCode = {
OK: 200,
BadRequest: 400,
Unauthorized: 401,
InternalServerError: 500
} as const;
type StatusCodeType = typeof StatusCode[keyof typeof StatusCode];
function processStatus(code: StatusCodeType) {
// ...
}
Union Type'lardan Foydalanish:
type StatusCode = 200 | 400 | 401 | 500;
function processStatus(code: StatusCode) {
// ...
}
Yana, union type'lar eng qisqa va samarali yechimni taklif qiladi. Const assertionlar kuchli muqobil bo'lib, ular berilgan holat kodi uchun ko'proq so'zli tavsif berganligi sababli afzal ko'rilishi mumkin. Enumlar tashqi kutubxonalar yoki API'lar butun sonlarga asoslangan holat kodlarini kutsa va siz uzluksiz integratsiyani ta'minlamoqchi bo'lsangiz foydali bo'lishi mumkin. Raqamli qiymatlar standart HTTP kodlariga mos keladi, bu esa mavjud tizimlar bilan o'zaro aloqani soddalashtirishi mumkin.
Ishlashga Doir Mulohazalar
Ko'pgina hollarda, enums, const assertionlar va union type'lar o'rtasidagi ishlash farqi ahamiyatsizdir. Biroq, ishlash-kritik ilovalarda, potentsial farqlardan xabardor bo'lish muhimdir.
- Enums: Enumlar JavaScript obyektlarini yaratish tufayli runtime xarajatlarni keltirib chiqaradi. Bu xarajatlar ko'plab enumlarga ega katta ilovalarda sezilarli bo'lishi mumkin.
- Const Assertions: Const assertionlarda runtime xarajatlar yo'q. Ular TypeScript tomonidan faqat o'qiladigan deb qabul qilinadigan oddiy JavaScript obyektlaridir.
- Union Types: Union type'larda runtime xarajatlar yo'q. Ular faqat kompilyatsiya vaqtida mavjud bo'lib, kompilyatsiya paytida o'chiriladi.
Agar ishlash asosiy tashvish bo'lsa, union type'lar odatda eng yaxshi tanlovdir. Const assertionlar ham yaxshi variant, ayniqsa sizga kalit-qiymat munosabati kerak bo'lsa. Kodning ishlash-kritik qismlarida enumlardan foydalanishdan saqlaning, agar buning uchun o'ziga xos sababingiz bo'lmasa.
Global Oqibatlar va Eng Yaxshi Amaliyotlar
Xalqaro jamoalar yoki global foydalanuvchilar bilan loyihalarda ishlashda lokalizatsiya va internatsionalizatsiyani hisobga olish juda muhimdir. Quyida global kontekstda enumlar va ularning muqobillaridan foydalanish bo'yicha eng yaxshi amaliyotlar keltirilgan:
- Tavsiflovchi nomlardan foydalaning: Enum a'zolari nomlarini (yoki const assertion kalitlarini) hatto ingliz tilida so'zlashmaydiganlar uchun ham aniq va bir ma'noli qilib tanlang. Jargon yoki xalq tilidan saqlaning.
- Lokalizatsiyani hisobga oling: Agar foydalanuvchilarga enum a'zolari nomlarini ko'rsatishingiz kerak bo'lsa, turli tillar uchun tarjimalarni ta'minlaydigan lokalizatsiya kutubxonasidan foydalanishni o'ylab ko'ring. Masalan, to'g'ridan-to'g'ri
Status.InProgressni ko'rsatish o'rniga, sizi18n.t('status.in_progress')ni ko'rsatishingiz mumkin. - Madaniyatga xos taxminlardan saqlaning: Enum qiymatlarini belgilashda madaniy farqlarni yodda tuting. Masalan, sana formatlari, valyuta belgilari va o'lchov birliklari madaniyatlar bo'ylab sezilarli darajada farq qilishi mumkin. Agar siz ushbu qiymatlarni ifodalashga ehtiyoj sezsangiz, lokalizatsiya va internatsionalizatsiyani boshqaradigan kutubxonadan foydalanishni o'ylab ko'ring.
- Kodingizni hujjatlashtiring: Enumlar va ularning muqobillari uchun aniq va qisqa hujjatlarni taqdim eting, ularning maqsadi va ishlatilishini tushuntiring. Bu boshqa dasturchilarga, ularning tajribasi yoki bilimidan qat'i nazar, kodingizni tushunishga yordam beradi.
Misol: Foydalanuvchi Rollarini Lokalizatsiya Qilish
Keling, foydalanuvchi rollari misolini qayta ko'rib chiqaylik va turli tillar uchun rol nomlarini qanday lokalizatsiya qilishni ko'rib chiqamiz.
// Using Const Assertions with Localization
const UserRole = {
Admin: 'admin',
Editor: 'editor',
Viewer: 'viewer',
} as const;
type UserRoleType = typeof UserRole[keyof typeof UserRole];
// Localization function (using a hypothetical i18n library)
function getLocalizedRoleName(role: UserRoleType, locale: string): string {
switch (role) {
case UserRole.Admin:
return i18n.t('user_role.admin', { locale });
case UserRole.Editor:
return i18n.t('user_role.editor', { locale });
case UserRole.Viewer:
return i18n.t('user_role.viewer', { locale });
default:
return 'Unknown Role';
}
}
// Example usage
const currentRole: UserRoleType = UserRole.Editor;
const localizedRoleName = getLocalizedRoleName(currentRole, 'fr-CA'); // Returns localized \"Éditeur\" for French Canadian.
console.log(`Current role: ${localizedRoleName}`);
Ushbu misolda biz foydalanuvchining tiliga qarab tarjima qilingan rol nomini olish uchun lokalizatsiya funksiyasidan foydalanamiz. Bu rol nomlarining foydalanuvchi afzal ko'rgan tilda ko'rsatilishini ta'minlaydi.
Xulosa
TypeScript enum'lar foydali xususiyat bo'lsa-da, ular har doim ham eng yaxshi tanlov emas. Const assertionlar va union type'lar yaxshiroq ishlash, o'zgarmaslik va kodni saqlash imkoniyatini beruvchi munosib alternativalarni taklif qiladi. Har bir yondashuvning afzalliklari va kamchiliklarini tushunish orqali siz loyihalaringizda qaysi birini ishlatish bo'yicha asosli qarorlar qabul qilishingiz mumkin. Ilovangizning o'ziga xos ehtiyojlarini, jamoangizning afzalliklarini va kodingizning uzoq muddatli saqlanishini hisobga oling. Ushbu omillarni diqqat bilan tortib, TypeScript loyihalaringizda konstantalarni aniqlash uchun eng yaxshi yondashuvni tanlashingiz, natijada toza, samaraliroq va parvarishlash osonroq kod bazalariga erishishingiz mumkin.