ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TypeScript의 enum에 대해서
    TypeScript 2023. 5. 19. 23:00

    타입스크립트에서 고정된 값을 주기위해서 다음과 같이 union을 활용할 수 있다.

    type Fruit = "Apple" | "Banana" | "Cocoa";
    
    const fruit: Fruit = "Apple";

    위에서 fruit은 자동완성도 지원되고, Apple, Banana, Cocoa 셋 중 하나의 값만 가질 수 있게 된다.

    다만, 다른 언어에 익숙한 사람이라면 enum을 사용하여 위의 고정된 선택지의 값을 표현하고 싶어할 수 있다.

    enum Fruit { 
      Apple,
      Banana,
      Cocoa
    }
    
    const fruit: Fruit = Fruit.Apple; // 0

    위의 타입스크립트는 다음과 같이 자바스크립트로 변환된다.

    "use strict";
    var Fruit;
    (function (Fruit) {
        Fruit[Fruit["Apple"] = 0] = "Apple";
        Fruit[Fruit["Banana"] = 1] = "Banana";
        Fruit[Fruit["Cocoa"] = 2] = "Cocoa";
    })(Fruit || (Fruit = {}));
    const fruit = Fruit.Apple; // 0

    타입스크립트 플레이그라운드에서 자바스크립트 변환을 직접 확인할 수 있다.

     

    하지만 타입스크립트에서의 enum은 몇가지 문제가 있다.

     

    Enum

    만약, 당신이 타입스크립트 v4를 사용중이라면, enum은 예상치 못한 오류를 도출할 수 있다.

    타입스크립트 v4.9.5에서 다음과 같은 코드는 아무런 문제를 발생시키지 않는다.

    // typescript v4.9.5
    enum Fruit { 
      Apple, // 0
      Banana, // 1
      Cocoa // 2
    }
    
    let fruit: Fruit = Fruit.Apple;
    fruit = 100;

    enum Fruit에는 100의 값을 가지지 않지만. fruit에는 100이 할당될 수 있는 문제가 발생한다.

     

    다만, 이 문제는 타입스크립트 v5가 되면서 해결되었다.

    // typescript v5.0.4
    enum Fruit { 
      Apple, // 0
      Banana, // 1
      Cocoa // 2
    }
    
    let fruit: Fruit = Fruit.Apple;
    fruit = 100; // Type '100' is not assignable to type 'Fruit'.(2322)

    이번엔 에러가 발생하는 것을 확인할 수 있다.

     

    v5에 이르러 enum의 치명적 문제가 해결되었긴 했지만, 여전히 타입스크립트에서 enum은 의문부호가 있다.

    타입스크립트는 대부분의 환경(Deno를 제외한 Node, 브라우저 등)에서 자바스크립트로 변환된 뒤 실행된다.

     

    타입스크립트의 enum은 자바스크립트로 변환되면서 불필요한 코드를 발생시킨다.

    // typescript v5.0.4
    enum Fruit { 
      Apple, // 0
      Banana, // 1
      Cocoa // 2
    }
    
    let fruit: Fruit = Fruit.Apple;
    console.log(Fruit);

    위의 타입스크립트는 자바스크립트가 되면서 다음과 같이 변환된다.

    "use strict";
    var Fruit;
    (function (Fruit) {
        Fruit[Fruit["Apple"] = 0] = "Apple";
        Fruit[Fruit["Banana"] = 1] = "Banana";
        Fruit[Fruit["Cocoa"] = 2] = "Cocoa"; // 2
    })(Fruit || (Fruit = {}));
    let fruit = Fruit.Apple;
    console.log(Fruit);

     

    만약 enum없이 타입스크립트 코드를 작성했다면 어땠을까?

    // typescript v5.0.4
    type Fruit = "Apple" | "Banana" | "Cocoa";
    
    let fruit: Fruit = "Apple";
    console.log(fruit);

    위의 코드는 다음과 같은 자바스크립트 코드가 된다.

    "use strict";
    let fruit = "Apple";
    console.log(fruit);

    확연히 코드가 짧아진 것을 알 수 있다.

    enum을 많이 사용하게 된다면, 자바스크립트 코드는 길어질것이고 자바스크립트 크기가 커지는 것은 네트워크 통신의 비용을 증가시키므로 별로 좋지 않은 옵션이다.

    🥖 다만, enum을 사용함으로써 사용자들이 불편을 느낄만큼 자바스크립트 크기가 커질지는 잘 모르겠다.

     

    그래도 enum처럼 하나의 객체 내부의 타입을 선택하는 모습을 선호한다면, 대체제로 다음과 같이 readonly한 프로퍼티를 가지는 객체를 만들 수 있다.

    const Fruit = {
      Apple: "Apple",
      Banana: "Banana",
      Cocoa: "Cocoa"
    } as const;
    
    const fruit = Fruit.Apple
    
    Fruit.Banana = "Text" // Cannot assign to 'Banana' because it is a read-only property.(2540)

     

    🍊 enum은 코드를 작성할 때 깔끔하고, 생산성을 높일 수 있는 멋진 방식이라고 생각한다. 다만, 타입스크립트에서 만큼은 도입하는데 신중해야할 것 같다.

     

    참고 자료

    https://blog.graphqleditor.com/enums-are-still-bad

     

    TypeScript enums in 5.0 (are they still bad?) | GraphQL Blog

    TypeScript 5.0 is here and it brings a lot of changes to performance, adds deco...

    blog.graphqleditor.com

     

Designed by Tistory.