TypeScript

TypeScript의 enum에 대해서

citron031 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