PorównaniePorównania

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.

Na tej stronie

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
  • 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

#
TypeScript
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)
Wynik
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

#
Składnia
enum Nazwa {
  Czlon = "wartosc"
}

type Nazwa = "wartosc1" | "wartosc2"

Więcej przykładów

#
enum istnieje jako obiekt w runtime
TypeScript
enum Difficulty {
  Easy = 'easy',
  Hard = 'hard'
}

console.log(Object.values(Difficulty))
console.log(typeof Difficulty)
Wynik
['easy', 'hard']
object
Unia literałów nie zostawia żadnego śladu w JavaScripcie
TypeScript
type Rank = 'bronze' | 'gold'

const current: Rank = 'gold'
console.log(current)
console.log(typeof Rank)
Wynik
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 const plus typeof daje podobny efekt do enuma: listę wartości do pętli i typ unii z jednej stałej.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.