În lumea programării cu TypeScript, structurile de date de tip enumerare (denumite și „enum-uri”) sunt concepte frecvent întâlnite și esențiale pentru dezvoltatori.
TypeScript, deși relativ tânăr, s-a impus ca unul dintre cele mai populare limbaje de programare printre dezvoltatori. Ca o extensie a JavaScript, TypeScript permite codului JavaScript valid să funcționeze fără probleme. Mai mult, el introduce avantajul tastării statice, o caracteristică absentă în JavaScript standard.
Dar ce sunt mai exact enumerările în TypeScript, în ce situații se utilizează și cum le putem crea? Acest articol explorează toate aspectele esențiale legate de enum-uri.
Ce reprezintă enumerările în TypeScript?
Enumerările sunt structuri de date de dimensiune fixă, concepute pentru a stoca un set de valori constante și predefinite. Ele nu sunt exclusivități TypeScript, fiind utilizate și în limbaje orientate pe obiecte precum C# și Java.
În TypeScript, enum-urile oferă dezvoltatorilor posibilitatea de a defini un set distinct de cazuri sau intenții. Ele sunt vitale pentru a seta valori sau proprietăți care pot lua doar un număr limitat de valori. Un exemplu concret este numărul de continente de pe Pământ, care este mereu șapte.
În concluzie, enumerările TypeScript sunt importante din mai multe motive:
- Oferă flexibilitate, permițând dezvoltatorilor să documenteze și să exprime intențiile și cazurile de utilizare într-un mod clar.
- Permit crearea de constante personalizate eficiente din punct de vedere energetic în JavaScript.
- Contribuie la optimizarea procesului de compilare și reducerea timpului de execuție la transformarea codului TypeScript în JavaScript.
Enumerările TypeScript pot fi numerice sau de tip șir. Este important de menționat că aceste structuri sunt preprocesate și nu sunt supuse verificărilor în timpul fazei de testare, fiind convertite în cod JavaScript de către compilatorul TypeScript.
Tipuri variate de enumerări în TypeScript
Acum, că avem o înțelegere clară a enum-urilor, este momentul să le vedem în acțiune. Putem configura un mediu de dezvoltare descărcând TypeScript și Node.js pe calculatorul nostru sau putem utiliza resurse online. Vom folosi TypeScript Playground pentru a ilustra diversele tipuri de enumerări.
Iată principalele tipuri de enumerări în TypeScript:
#1. Enumerări numerice
Pentru a defini o enumerare numerică, se utilizează cuvântul cheie „enum”, urmat de numele dorit al enumerării și de paranteze acolade care vor conține membrii acesteia. Iată un exemplu:
enum CardinalDirections { North = 5, East, South, West, };
Acest exemplu definește o enumerare numită `CardinalDirections` cu patru membri. Există doar patru valori posibile (Nord, Est, Sud și Vest), ceea ce face ca enumerarea să fie ideală pentru stocarea acestui tip de date.
Am atribuit `CardinalDirections.North` valoarea 5. Valorile pentru restul membrilor sunt atribuite automat de TypeScript, prin incrementarea cu 1 a valorii membrului precedent. Astfel, `CardinalDirections.East` va avea valoarea 6.
Similar, `CardinalDirections.West` va avea valoarea 8.
Ce se întâmplă dacă nu atribuim o valoare primului membru? Vom avea:
enum CardinalDirections { North, East, South, West, };
În acest caz, TypeScript va atribui automat valoarea 0 membrului `North`. Deci, `CardinalDirections.West` va avea valoarea 3.
#2. Enumerări șir
Fiecare membru dintr-o enumerare de tip șir trebuie inițializat cu un alt membru de tip șir sau cu un literal șir. Iată un exemplu:
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", }
Spre deosebire de enumerările numerice, enumerările de tip șir nu se incrementează automat. Dacă executăm codul de mai jos:
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", } console.log(Direction.Right);
Vom obține următorul rezultat:
„RIGHT”
#3. Enumerări eterogene
Într-o enumerare eterogenă se pot combina membri numerici și de tip șir. Iată un exemplu:
enum HeterogeneousEnum { No = 0, Yes = "YES", }
#4. Membri enum constanți și calculați
Membrii enum au valori asociate care pot fi „constante” sau „calculate”.
Un exemplu de enumerare cu membri constanți este:
enum E1 { X, Y, Z, }
În acest caz, primul membru al enumerării nu are un inițializator, iar TypeScript îi atribuie valoarea 0.
Putem lua în considerare și acest exemplu:
enum E1 { X=1, Y, Z, }
Și acesta este un exemplu de enumerare constantă, deoarece primului membru i se atribuie o valoare, iar regula incrementală se aplică restului.
Enumerările cu membri calculați combină membri constanți și calculați. Iată un exemplu:
enum Color { Red = 100, Green = (Math.random() * 100), Blue = 200 }
Membrul enum „Blue” este un membru constant. Membrul enum „Green” este un membru calculat, având valoarea determinată de funcția `Math.random()` la momentul execuției.
#5. Enumerări const
Enumerările const sunt folosite pentru a crește performanța enumerărilor numerice. În acest caz, declarăm enumerarea ca o constantă.
Să luăm ca exemplu zilele săptămânii:
enum Weekday { Monday = 1, Tuesday, Wednesday, Thursday, Friday }
Dacă executăm `console.log(Weekday.Thursday)`, vom primi răspunsul 4. Dacă verificăm codul JavaScript generat în timpul compilării, vom observa următoarele:
"use strict"; var Weekday; (function (Weekday) { Weekday[Weekday["Monday"] = 1] = "Monday"; Weekday[Weekday["Tuesday"] = 2] = "Tuesday"; Weekday[Weekday["Wednesday"] = 3] = "Wednesday"; Weekday[Weekday["Thursday"] = 4] = "Thursday"; Weekday[Weekday["Friday"] = 5] = "Friday"; })(Weekday || (Weekday = {})); console.log(Weekday.Thursday);
Putem modifica acest cod și declara `Weekday` ca o constantă:
const enum Weekday { Monday = 1, Tuesday, Wednesday, Thursday, Friday }
Dacă executăm `console.log(Weekday.Thursday)`, codul JavaScript generat va fi:
"use strict"; console.log(4 /* Weekday.Thursday */);
Se observă că, la compilare, codul JavaScript este optimizat atunci când declarăm o enumerare ca `const`.
#6. Enumerări ambientale
Enumerările ambientale folosesc cuvântul cheie `declare` pentru a descrie structura unor tipuri de enumerări care există deja. Iată un exemplu:
declare enum Color { Red, Green, Blue }
Enumerările ambientale sunt declarate în afara oricărui modul și pot fi utilizate pentru a crea tipuri reutilizabile. Astfel, putem importa oricând enumerările ambientale și le putem utiliza în componentele noastre, cu condiția ca acestea să fie declarate la nivel global.
Acum, că înțelegem diversele tipuri de enumerări din TypeScript, putem ilustra cum se pot utiliza acestea în diferite scenarii, având ca referință codul de mai jos:
enum Direction { North="N", East="E", South="S", West="W", };
Iată câteva cazuri de utilizare:
- Extragerea membrilor enumerați. De exemplu, dacă vrem să accesăm `North`, putem folosi:
`console.log(Direction.North);` // Afișează: „N”
- Utilizarea membrilor enumerării: se poate selecta un anumit membru al enum-ului pentru a reprezenta o anumită direcție. De exemplu:
const currentDirection = Direction.East; console.log(`The current direction is ${currentDirection}`);
Aceasta va afișa rezultatul: „Direcția curentă este E”
Enum-uri vs. Object Maps în TypeScript
Enumerările sunt utilizate pentru a reprezenta un set finit de valori, cum ar fi culorile curcubeului sau zilele săptămânii. Acestea sunt puternic tipizate, ceea ce înseamnă că pot identifica erorile în timpul dezvoltării. Iată un exemplu de enumerare TypeScript:
enum Color { Red, Green, Blue, }
Hărțile de obiecte (sau dicționarele) stochează și preiau valori asociate cu anumite chei. În TypeScript, hărțile de obiecte pot stoca orice tip de date. Totuși, ele nu sunt strict tipizate, deci erorile de tip pot să nu fie detectate în timpul dezvoltării. Iată un exemplu de hartă de obiecte pentru aceleași culori:
const colors = { red: "FF0000", green: "00FF00", blue: "0000FF", };
Principalele diferențe dintre enumerări și hărțile de obiecte în TypeScript sunt:
- Enumerările sunt strict tipizate, în timp ce hărțile de obiecte nu sunt.
- Enumerările reprezintă un „Tip”, în timp ce hărțile de obiecte sunt structuri de date.
- Enumerările nu sunt flexibile, în timp ce hărțile de obiecte sunt flexibile.
Cele mai bune practici pentru utilizarea enumerărilor în TypeScript
Am menționat deja că TypeScript nu este singurul limbaj care folosește enumerări. Respectarea celor mai bune practici garantează un cod curat, optimizat și fără erori. Iată câteva recomandări pentru lucrul cu enumerări în TypeScript:
- Utilizați majuscule la denumirea enumerărilor: scrieți cu majusculă primul cuvânt din numele unei enumerări. De exemplu, preferați să numiți o enumerare `Număr` în loc de `număr`.
- Folosiți enumerări pentru constante: enumerările sunt cele mai potrivite pentru a declara un set fix de elemente corelate. De exemplu, zilele dintr-o săptămână sunt mereu șapte. Membrii enumerării nu ar trebui să se schimbe în timpul execuției.
- Evitați suprautilizarea enumerărilor: chiar dacă ați învățat un concept nou, folosiți enumerările cu moderație. Ele sunt o alegere bună pentru a menține lizibilitatea codului.
- Tratați enumerările ca enumerări: puteți folosi enumerările în mai multe scopuri, dar cel mai bine este să le utilizați doar pentru a reprezenta enumerări, nu alte structuri de date.
- Evitați enumerarea automată: TypeScript atribuie valori membrilor enumerării dacă nu o faceți explicit. Atribuiți valorile în mod explicit pentru a evita comportamente neașteptate.
- Documentați enumerările: documentați sau comentați codul, mai ales dacă este destinat unui public larg. Explicați ce face fiecare enumerare și de ce este utilă.
Vă încurajăm să explorați și biblioteci TypeScript populare pentru a vă îmbunătăți cunoștințele ca dezvoltator.
Concluzie
Am definit enumerările în TypeScript și am explicat diferitele lor tipuri și cazuri de utilizare. TypeScript este util pentru claritatea codului. Totuși, sunt și situații în care ar trebui să le evitați și să folosiți obiecte în schimb.
De exemplu, nu ar trebui să folosiți enumerări când lucrați cu valori dinamice. De asemenea, nu puteți folosi enumerările ca variabile, deoarece veți primi erori.
Dacă încă sunteți confuz de diferențele dintre TypeScript și JavaScript, vă recomandăm să aprofundați aceste aspecte.