Enumlar uchun TypeScript-ning kuchli alternativalarini o'rganing: const assertions va union types. Qaysi birini mustahkam, saqlanadigan kod uchun ishlatishni bilib oling.
Enumlardan tashqari: TypeScript Const Assertions va Union Types
TypeScript bilan statik typed JavaScript olamida, enumlar uzoq vaqtdan beri nomlangan konstantalarning belgilangan to'plamini ifodalash uchun ishlatilgan. Ular bog'liq qiymatlar to'plamini aniqlashning aniq va o'qilishi oson usulini taklif qilishadi. Biroq, loyihalar o'sib, rivojlanar ekan, dasturchilar ko'proq moslashuvchan va ba'zan yanada samaraliroq alternativalarni qidiradilar. Tez-tez paydo bo'ladigan ikkita kuchli da'vogar - const assertions va union types. Ushbu post an'anaviy enumlarga ushbu alternativalardan foydalanishning nozikliklarini o'rganadi, amaliy misollar keltiradi va qaysi birini tanlash bo'yicha sizga yo'l-yo'riq ko'rsatadi.
An'anaviy TypeScript Enumlarini tushunish
Alternativalarni o'rganishdan oldin, standart TypeScript enumlari qanday ishlashini yaxshi tushunish muhim. Enumlar sizga nomlangan sonli yoki string konstantalar to'plamini aniqlashga imkon beradi. Ular sonli (standart) yoki string asosida bo'lishi mumkin.
Sonli Enumlar
Standart bo'yicha, enum a'zolariga 0 dan boshlab sonli qiymatlar beriladi.
enum DirectionNumeric {
Up,
Down,
Left,
Right
}
let myDirection: DirectionNumeric = DirectionNumeric.Up;
console.log(myDirection); // Natija: 0
Bundan tashqari, siz sonli qiymatlarni aniq belgilashingiz mumkin.
enum StatusCode {
Success = 200,
NotFound = 404,
InternalError = 500
}
let responseStatus: StatusCode = StatusCode.Success;
console.log(responseStatus); // Natija: 200
String Enumlar
String enumlar ko'pincha yaxshilangan debugging tajribasi uchun afzal ko'riladi, chunki a'zo nomlari kompilyatsiya qilingan JavaScript-da saqlanadi.
enum ColorString {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
let favoriteColor: ColorString = ColorString.Blue;
console.log(favoriteColor); // Natija: "BLUE"
Enumning ortiqcha yuklamasi
Enumlar qulay bo'lsa-da, ular biroz ortiqcha yuk bilan birga keladi. JavaScript-ga kompilyatsiya qilinganda, TypeScript enumlari ko'pincha teskari xaritalashga ega bo'lgan ob'ektlarga aylanadi (masalan, sonli qiymatni enum nomiga qaytarish). Bu foydali bo'lishi mumkin, ammo paket hajmining oshishiga ham hissa qo'shadi va har doim ham zarur bo'lmasligi mumkin.
Ushbu oddiy string enumini ko'rib chiqing:
enum Status {
Pending = "PENDING",
Processing = "PROCESSING",
Completed = "COMPLETED"
}
JavaScript-da bu quyidagicha bo'lishi mumkin:
var Status;
(function (Status) {
Status["Pending"] = "PENDING";
Status["Processing"] = "PROCESSING";
Status["Completed"] = "COMPLETED";
})(Status || (Status = {}));
Konstantalarning oddiy, faqat o'qish mumkin bo'lgan to'plamlari uchun ushbu yaratilgan kod biroz haddan tashqari bo'lishi mumkin.
Alternativa 1: Const Assertions
Const assertions - bu TypeScript-ning kuchli xususiyati bo'lib, u kompilyatorga qiymat uchun eng aniq turni aniqlashni aytishga imkon beradi. Belgilangan qiymatlar to'plamini ifodalashga mo'ljallangan massivlar yoki ob'ektlar bilan ishlatilganda, ular enumlar uchun engil alternativa bo'lib xizmat qilishi mumkin.
Massivlar bilan Const Assertions
Siz string literallarining massivini yaratishingiz va keyin uning turini o'zgarmas va uning elementlarini literal turlariga aylantirish uchun const assertionidan foydalanishingiz mumkin.
const statusArray = ["PENDING", "PROCESSING", "COMPLETED"] as const;
type StatusType = typeof statusArray[number];
let currentStatus: StatusType = "PROCESSING";
// currentStatus = "FAILED"; // Xato: '"FAILED"' turi 'StatusType' turiga tayinlanmaydi.
function processStatus(status: StatusType) {
console.log(`Jarayon holati: ${status}`);
}
processStatus("COMPLETED");
Keling, bu erda nima sodir bo'layotganini ko'rib chiqaylik:
as const: Ushbu assertion TypeScript-ga massivni faqat o'qish mumkin deb hisoblashni va uning elementlari uchun eng aniq literal turlarini aniqlashni aytadi. Shunday qilib, `string[]` o'rniga turi `readonly ["PENDING", "PROCESSING", "COMPLETED"]` ga aylanadi.typeof statusArray[number]: Bu xaritalash turi. UstatusArrayning barcha indekslari bo'ylab takrorlanadi va ularning literal turlarini chiqaradi.numberindeks imzo, asosan, "menga ushbu massivdagi har qanday elementning turini bering" deydi. Natija union turi:"PENDING" | "PROCESSING" | "COMPLETED".
Ushbu yondashuv string enumlariga o'xshash tur xavfsizligini ta'minlaydi, ammo minimal JavaScript yaratadi. statusArray ning o'zi JavaScript-da stringlar massivi bo'lib qoladi.
Ob'ektlar bilan Const Assertions
Const assertions ob'ektlarga qo'llanilganda yanada kuchliroqdir. Siz kalitlar nomlangan konstantalaringizni, qiymatlar esa literal stringlar yoki raqamlar bo'lgan ob'ektni aniqlashingiz mumkin.
const userRoles = {
Admin: "ADMIN",
Editor: "EDITOR",
Viewer: "VIEWER"
} as const;
type UserRole = typeof userRoles[keyof typeof userRoles];
let currentUserRole: UserRole = "EDITOR";
// currentUserRole = "GUEST"; // Xato: '"GUEST"' turi 'UserRole' turiga tayinlanmaydi.
function displayRole(role: UserRole) {
console.log(`Foydalanuvchi roli: ${role}`);
}
displayRole(userRoles.Admin); // Yaroqli
displayRole("EDITOR"); // Yaroqli
Ushbu ob'ekt misolida:
as const: Ushbu assertion butun ob'ektni faqat o'qish mumkin qiladi. Muhimi shundaki, u barcha xususiyat qiymatlari uchun literal turlarini (masalan,stringo'rniga"ADMIN") aniqlaydi va xususiyatlarning o'zini faqat o'qish mumkin qiladi.keyof typeof userRoles: Ushbu ifodauserRolesob'ektining kalitlarining birikmasiga olib keladi, bu"Admin" | "Editor" | "Viewer".typeof userRoles[keyof typeof userRoles]: Bu qidiruv turi. U kalitlar birikmasini oladi va undanuserRolesturidagi mos keladigan qiymatlarni qidirish uchun foydalanadi. Bu qiymatlarning birikmasiga olib keladi:"ADMIN" | "EDITOR" | "VIEWER", bu rollar uchun bizning kerakli turimiz.
userRoles uchun JavaScript chiqishi oddiy JavaScript ob'ekti bo'ladi:
var userRoles = {
Admin: "ADMIN",
Editor: "EDITOR",
Viewer: "VIEWER"
};
Bu odatdagi enumdan ancha engilroq.
Const Assertionsdan qachon foydalanish kerak
- Faqat o'qish mumkin bo'lgan konstantalar: Agar sizga ish vaqtida o'zgarmasligi kerak bo'lgan string yoki raqamli literallarning belgilangan to'plami kerak bo'lsa.
- Minimal JavaScript chiqishi: Agar siz paket hajmidan xavotirda bo'lsangiz va konstantalaringiz uchun eng samarali ish vaqti ko'rinishini xohlasangiz.
- Ob'ektga o'xshash tuzilma: Agar siz ma'lumotlar yoki konfiguratsiyani qanday tuzishingiz mumkinligiga o'xshash kalit-qiymat juftliklarining o'qilishini afzal ko'rsangiz.
- Stringga asoslangan to'plamlar: Ta'riflovchi stringlar bilan eng yaxshi aniqlangan holatlar, turlar yoki kategoriyalarni ifodalash uchun ayniqsa foydali.
Alternativa 2: Union Types
Union types sizga o'zgaruvchi bir nechta turlardan birining qiymatini ushlab turishi mumkinligini e'lon qilishga imkon beradi. Literal turlar (string, number, boolean literallari) bilan birlashtirilganda, ular to'plam uchun aniq konstantani e'lon qilmasdan ruxsat etilgan qiymatlar to'plamini aniqlashning kuchli usulini hosil qiladi.
String Literallari bilan Union Types
Siz to'g'ridan-to'g'ri string literallarining birikmasini aniqlashingiz mumkin.
type TrafficLightColor = "RED" | "YELLOW" | "GREEN";
let currentLight: TrafficLightColor = "YELLOW";
// currentLight = "BLUE"; // Xato: '"BLUE"' turi 'TrafficLightColor' turiga tayinlanmaydi.
function changeLight(color: TrafficLightColor) {
console.log(`Chiroqni o'zgartirish: ${color}`);
}
changeLight("RED");
// changeLight("REDDY"); // Xato
Bu ruxsat etilgan string qiymatlari to'plamini aniqlashning eng to'g'ri va ko'pincha eng qisqa usuli.
Sonli Literallari bilan Union Types
Xuddi shunday, siz sonli literallardan foydalanishingiz mumkin.
type HttpStatusCode = 200 | 400 | 404 | 500;
let responseCode: HttpStatusCode = 404;
// responseCode = 201; // Xato: '201' turi 'HttpStatusCode' turiga tayinlanmaydi.
function handleResponse(code: HttpStatusCode) {
if (code === 200) {
console.log("Muvaffaqiyat!");
} else {
console.log(`Xato kodi: ${code}`);
}
}
handleResponse(500);
Union Typesdan qachon foydalanish kerak
- Oddiy, to'g'ridan-to'g'ri to'plamlar: Ruxsat etilgan qiymatlar to'plami kichik, aniq bo'lganda va qiymatlarning o'zidan tashqari ta'riflovchi kalitlarni talab qilmasa.
- Yashirin konstantalar: To'plam uchun nomlangan konstantaga murojaat qilish zarur bo'lmaganda, aksincha to'g'ridan-to'g'ri literal qiymatlardan foydalaning.
- Maksimal qisqalik: Maxsus ob'ekt yoki massivni aniqlash haddan tashqari ko'rinadigan oddiy stsenariylar uchun.
- Funksiya parametrlari/qaytish turlari: Funktsiyalar uchun qabul qilinadigan string yoki raqamli kirish/chiqishlarning aniq to'plamini aniqlash uchun juda yaxshi.
Enumlar, Const Assertions va Union Typesni taqqoslash
Keling, asosiy farqlar va foydalanish holatlarini umumlashtiraylik:
Ish vaqti xatti-harakati
- Enumlar: JavaScript ob'ektlarini yaratadi, ehtimol teskari xaritalashlar bilan.
- Const Assertions (Massivlar/Ob'ektlar): Oddiy JavaScript massivlari yoki ob'ektlarini yaratadi. Tur haqidagi ma'lumot ish vaqtida o'chiriladi, ammo ma'lumotlar tuzilmasi saqlanib qoladi.
- Union Types (literallar bilan): Birikmaning o'zi uchun ish vaqti ko'rinishi yo'q. Qiymatlar shunchaki literallar. Turni tekshirish faqat kompilyatsiya vaqtida sodir bo'ladi.
O'qilishi va ifodaliligi
- Enumlar: Yuqori o'qilish, ayniqsa ta'riflovchi nomlar bilan. Batafsilroq bo'lishi mumkin.
- Const Assertions (Ob'ektlar): Kalit-qiymat juftliklari orqali yaxshi o'qilish, konfiguratsiyalar yoki sozlamalarga taqlid qilish.
- Const Assertions (Massivlar): Nomlangan konstantalarni ifodalash uchun kamroq o'qiladigan, qiymatlarning tartiblangan ro'yxati uchun ko'proq.
- Union Types: Juda qisqa. O'qilish literal qiymatlarning aniqligiga bog'liq.
Tur xavfsizligi
- Uchala yondashuv ham kuchli tur xavfsizligini ta'minlaydi. Ular faqat yaroqli, oldindan belgilangan qiymatlar o'zgaruvchilarga tayinlanishi yoki funktsiyalarga o'tkazilishini ta'minlaydi.
Paket hajmi
- Enumlar: Odatda yaratilgan JavaScript ob'ektlari tufayli eng katta.
- Const Assertions: Enumlardan kichikroq, chunki ular oddiy ma'lumotlar tuzilmalarini yaratadilar.
- Union Types: Eng kichigi, chunki ular tur uchun hech qanday maxsus ish vaqti ma'lumotlar tuzilmasini yaratmaydi, faqat literal qiymatlarga tayanadi.
Foydalanish holatlari jadvali
Mana tezkor qo'llanma:
| Xususiyat | TypeScript Enum | Const Assertion (Ob'ekt) | Const Assertion (Massiv) | Union Type (Literallar) |
|---|---|---|---|---|
| Ish vaqti chiqishi | JS ob'ekti (teskari xaritalash bilan) | Oddiy JS ob'ekti | Oddiy JS massivi | Yo'q (faqat literal qiymatlar) |
| O'qilish (Nomlangan konstantalar) | Yuqori | Yuqori | O'rta | Past (qiymatlar nomlar) |
| Paket hajmi | Eng katta | O'rta | O'rta | Eng kichik |
| Moslashuvchanlik | Yaxshi | Yaxshi | Yaxshi | A'lo (oddiy to'plamlar uchun) |
| Umumiy foydalanish | Holatlar, holat kodlari, kategoriyalar | Konfiguratsiya, rol ta'riflari, funksiya bayroqlari | O'zgarmas qiymatlarning tartiblangan ro'yxati | Funksiya parametrlari, oddiy cheklangan qiymatlar |
Amaliy misollar va eng yaxshi amaliyotlar
1-misol: API holat kodlarini ifodalash
Enum:
enum ApiStatus {
Success = "SUCCESS",
Error = "ERROR",
Pending = "PENDING"
}
function handleApiResponse(status: ApiStatus) {
// ... logika ...
}
Const Assertion (Ob'ekt):
const apiStatusCodes = {
SUCCESS: "SUCCESS",
ERROR: "ERROR",
PENDING: "PENDING"
} as const;
type ApiStatus = typeof apiStatusCodes[keyof typeof apiStatusCodes];
function handleApiResponse(status: ApiStatus) {
// ... logika ...
}
Union Type:
type ApiStatus = "SUCCESS" | "ERROR" | "PENDING";
function handleApiResponse(status: ApiStatus) {
// ... logika ...
}
Tavsiya: Ushbu stsenariy uchun union type ko'pincha eng qisqa va samarali hisoblanadi. Literal qiymatlarning o'zi etarli darajada ta'riflovchi. Agar siz har bir holat bilan qo'shimcha metama'lumotlarni bog'lashingiz kerak bo'lsa (masalan, foydalanuvchilarga qulay xabar), const assertion ob'ekti yaxshiroq tanlov bo'ladi.
2-misol: Foydalanuvchi rollarini aniqlash
Enum:
enum UserRoleEnum {
Admin = "ADMIN",
Moderator = "MODERATOR",
User = "USER"
}
function getUserPermissions(role: UserRoleEnum) {
// ... logika ...
}
Const Assertion (Ob'ekt):
const userRolesObject = {
Admin: "ADMIN",
Moderator: "MODERATOR",
User: "USER"
} as const;
type UserRole = typeof userRolesObject[keyof typeof userRolesObject];
function getUserPermissions(role: UserRole) {
// ... logika ...
}
Union Type:
type UserRole = "ADMIN" | "MODERATOR" | "USER";
function getUserPermissions(role: UserRole) {
// ... logika ...
}
Tavsiya: Const assertion ob'ekti bu erda yaxshi muvozanatni ta'minlaydi. U aniq kalit-qiymat juftliklarini taqdim etadi (masalan, userRolesObject.Admin), bu rollarga murojaat qilganda o'qilishni yaxshilaydi, shu bilan birga samarali bo'ladi. Agar to'g'ridan-to'g'ri string literallari etarli bo'lsa, union type ham juda kuchli da'vogar.
3-misol: Konfiguratsiya parametrlarini ifodalash
Turli xil mavzularga ega bo'lishi mumkin bo'lgan global ilova uchun konfiguratsiya ob'ektini tasavvur qiling.
Enum:
enum Theme {
Light = "light",
Dark = "dark",
System = "system"
}
interface AppConfig {
theme: Theme;
// ... boshqa konfiguratsiya parametrlari ...
}
Const Assertion (Ob'ekt):
const themes = {
Light: "light",
Dark: "dark",
System: "system"
} as const;
type Theme = typeof themes[keyof typeof themes];
interface AppConfig {
theme: Theme;
// ... boshqa konfiguratsiya parametrlari ...
}
Union Type:
type Theme = "light" | "dark" | "system";
interface AppConfig {
theme: Theme;
// ... boshqa konfiguratsiya parametrlari ...
}
Tavsiya: Mavzular kabi konfiguratsiya sozlamalari uchun const assertion ob'ekti ko'pincha idealdir. U mavjud variantlarni va ularning tegishli string qiymatlarini aniq belgilaydi. Kalitlar (Light, Dark, System) ta'riflovchi va to'g'ridan-to'g'ri qiymatlarga xaritalashadi, bu konfiguratsiya kodini juda tushunarli qiladi.
Ish uchun to'g'ri vositani tanlash
TypeScript enumlari, const assertions va union types o'rtasidagi qaror har doim ham oq va qora emas. Ko'pincha ish vaqti ishlashi, paket hajmi va kodning o'qilishi/ifodalanishi o'rtasida murosaga keladi.
- Union Types ni tanlang, agar sizga string yoki raqamli literallarning oddiy, cheklangan to'plami kerak bo'lsa va maksimal qisqalik kerak bo'lsa. Ular funktsiya imzolari va qiymat cheklovlari uchun juda yaxshi.
- Const Assertions (Ob'ektlar bilan) ni tanlang, agar siz nomlangan konstantalarni aniqlashning ko'proq tuzilgan, o'qiladigan usulini xohlasangiz, enumga o'xshash, lekin sezilarli darajada kamroq ish vaqti xarajatlari bilan. Bu konfiguratsiya, rollar yoki kalitlar muhim ma'no qo'shadigan har qanday to'plam uchun juda yaxshi.
- Const Assertions (Massivlar bilan) ni tanlang, agar sizga shunchaki o'zgarmas qiymatlarning tartiblangan ro'yxati kerak bo'lsa va indeks orqali to'g'ridan-to'g'ri kirish nomlangan kalitlardan ko'ra muhimroq bo'lsa.
- Agar sizga ularning o'ziga xos xususiyatlari, masalan, teskari xaritalash (garchi bu zamonaviy rivojlanishda kamroq uchrasa ham) kerak bo'lsa yoki sizning jamoangizda kuchli afzallik bo'lsa va sizning loyihangiz uchun unumdorlik ta'siri ahamiyatsiz bo'lsa, TypeScript Enumlarini ko'rib chiqing.
Ko'pgina zamonaviy TypeScript loyihalarida siz an'anaviy enumlarga nisbatan const assertions va union types ga moyillikni topasiz, ayniqsa stringga asoslangan konstantalar uchun, ularning yaxshi ishlash xususiyatlari va ko'pincha oddiyroq JavaScript chiqishi tufayli.
Global mulohazalar
Global auditoriya uchun ilovalarni ishlab chiqishda izchil va bashorat qilinadigan doimiy ta'riflar juda muhimdir. Biz muhokama qilgan tanlovlar (enumlar, const assertions, union types) turli muhitlar va dasturchi joylashuvlarida tur xavfsizligini ta'minlash orqali ushbu izchillikka hissa qo'shadi.
- Izchillik: Tanlangan usuldan qat'i nazar, asosiysi loyihangizdagi izchillikdir. Agar siz rollar uchun const assertion ob'ektlaridan foydalanishga qaror qilsangiz, kod bazasi bo'ylab ushbu naqshga rioya qiling.
- Internatsionallashtirish (i18n): Internatsionallashtiriladigan yorliqlar yoki xabarlarni aniqlashda faqat yaroqli kalitlar yoki identifikatorlardan foydalanilishini ta'minlash uchun ushbu tur xavfsiz tuzilmalardan foydalaning. Haqiqiy tarjima qilingan stringlar i18n kutubxonalari orqali alohida boshqariladi. Misol uchun, agar sizda `status` maydoni bo'lsa, u "PENDING", "PROCESSING", "COMPLETED" bo'lishi mumkin, sizning i18n kutubxonangiz ushbu ichki identifikatorlarni mahalliy displey matniga xaritalaydi.
- Vaqt zonalari va valyutalari: Enumlar bilan to'g'ridan-to'g'ri bog'liq bo'lmasa-da, sanalar, vaqtlar yoki valyutalar kabi qiymatlar bilan ishlashda TypeScript tur tizimi to'g'ri foydalanishni ta'minlashga yordam berishi mumkinligini unutmang, ammo aniq global ishlash uchun tashqi kutubxonalar odatda zarurdir. Misol uchun, `Currency` union turi `"USD" | "EUR" | "GBP"` sifatida aniqlanishi mumkin, ammo haqiqiy konvertatsiya logikasi ixtisoslashtirilgan vositalarni talab qiladi.
Xulosa
TypeScript konstantalarni boshqarish uchun boy vositalar to'plamini taqdim etadi. Enumlar bizga yaxshi xizmat qilgan bo'lsa-da, const assertions va union types majburiy, ko'pincha yanada samaraliroq alternativalarni taklif qiladi. Ularning farqlarini tushunib, o'zingizning ehtiyojlaringizga asoslanib to'g'ri yondashuvni tanlash orqali - bu unumdorlik, o'qilish yoki qisqalik bo'ladimi - siz yanada mustahkam, saqlanadigan va samarali TypeScript kodini yoza olasiz, uni global miqyosda kengaytirish mumkin.
Ushbu alternativalarni qabul qilish kichikroq paket o'lchamlariga, tezroq ilovalarga va xalqaro jamoangiz uchun yanada bashorat qilinadigan ishlab chiquvchi tajribasiga olib kelishi mumkin.