enum vs union
enum tworzy nazwany zestaw stałych, który istnieje też w działającym programie jako obiekt, a unia literałów to tylko typ, lżejszy i bez żadnego kodu w JavaScripcie.
Porównanie w tabeli
#Istnieje w działającym programie (JavaScript)
- enum
- Tak, jako obiekt
- Unia (A | B)
- Nie, tylko podczas kompilacji
Zapis wartości
- enum
- Przez nazwę członu, np.
Difficulty.Hard - Unia (A | B)
- Bezpośrednio literał, np.
"hard"
Dodaje kod do paczki
- enum
- Tak
- Unia (A | B)
- Nie
Iterowanie po wariantach w runtime
- enum
- Tak, np.
Object.values() - Unia (A | B)
- Nie, potrzebna osobna tablica
Łączenie z innymi typami (unia, przecięcie)
- enum
- Ograniczone
- Unia (A | B)
- Naturalne, to też jest unia
Typowe użycie
- enum
- Gdy potrzebny też obiekt w runtime
- Unia (A | B)
- Dane z API, propsy w JSX, większość nowego kodu
Przykład
#enum StatusEnum {
Draft = 'draft',
Published = 'published'
}
type StatusUnion = 'draft' | 'published'
const fromEnum: StatusEnum = StatusEnum.Published
const fromUnion: StatusUnion = 'published'
console.log(fromEnum, fromUnion, fromEnum === fromUnion)published published true
Definicja i zastosowanie
#Obie konstrukcje ograniczają zmienną do jednego z kilku dozwolonych wariantów i obie dobrze sprawdzają się jako status, poziom trudności czy rola użytkownika. Kompilator w obu przypadkach zgłosi błąd, jeśli przypiszesz wartość spoza zbioru.
Różnią się tym, co powstaje po kompilacji. enum generuje prawdziwy obiekt JavaScript, do którego odwołujesz się przez nazwę (Difficulty.Hard), a jego wartości możesz przeglądać w czasie działania programu, np. przez Object.values(). Unia literałów ("easy" | "hard") istnieje tylko podczas kompilacji i znika bez śladu. Zamiast nazwy członu wpisujesz bezpośrednio wartość, czyli sam literał.
Gdy potrzebujesz też obiektu w działającym programie, na przykład do iterowania po wariantach albo do mapowania numer-nazwa, enum bywa wygodny. W większości nowego kodu, zwłaszcza przy danych z API i w JSX, prostsza i lżejsza jest unia literałów, bo nie dodaje żadnego kodu do paczki.
Składnia
#enum Nazwa {
Czlon = "wartosc"
}
type Nazwa = "wartosc1" | "wartosc2"Więcej przykładów
#enum Difficulty {
Easy = 'easy',
Hard = 'hard'
}
console.log(Object.values(Difficulty))
console.log(typeof Difficulty)['easy', 'hard'] object
type Rank = 'bronze' | 'gold'
const current: Rank = 'gold'
console.log(current)
console.log(typeof Rank)gold undefined
Rank jest tu tylko typem, więc po kompilacji nie istnieje jako zmienna. typeof na nieistniejącej nazwie nie rzuca błędu, tylko zwraca "undefined".
Dobre praktyki
#- Jeśli dane pochodzą z API jako napisy, string enum i unia literałów są prawie równoważne. Wybierz unię, chyba że potrzebujesz obiektu do iterowania.
- Enum liczbowy (
enum Status { Draft, Published }) bywa mylący w logach, bo wypisuje liczbę, nie nazwę. Enum tekstowy albo unia są czytelniejsze. - Wzór
as constplustypeofdaje podobny efekt do enuma: listę wartości do pętli i typ unii z jednej stałej.
Powiązane hasła
#- enumNazwany zestaw stałych wartości, liczbowych lub tekstowych.
- Unia (A | B)Typ, który może być jednym z kilku typów.
- Typy literałoweTypy dopuszczające tylko konkretne wartości, np. "easy" | "hard".
- as constZamraża literały w wyrażeniu: najwęższe typy i pola tylko do odczytu.
- Unie rozróżnialneUnie obiektów ze wspólnym polem-etykietą, które pozwala łatwo odróżnić warianty.
Widzisz błąd albo brakuje przykładu? Napisz do nas.