> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/typescript/undefined/enum.md).

# Enum

## Enum(열거형)이란?

* 자바스크립트에 없는 타입이지만, 자바스크립트의 값으로 사용할 수 있는 타입
* 여러 상수를 나열하는 목적으로 사용된다.
* `enum` 이라는 예약어로 선언한다.

```typescript
enum Node {
  Mesh, // enum 내부에 있는 이름을 멤버(member)라 부른다.
  Texture,
  Decal,
}
```

* enum은 자바스크립트 코드로 변환된다.

```javascript
var Node = {
  0: 'Mesh',
  1: 'Texture',
  2: 'Decal',
  Mesh: 0,
  Texture: 1,
  Decal: 2,
}
```

* enum의 멤버 순서대로 0부터 숫자가 할당된다.
  * 임의의 숫자를 할당하게 되면 그 다음 멤버의 값은 이전 값의 +1로 할당된다.
* 문자열도 할당 가능한데, 한 멤버를 문자열로 할당하면 그 뒤에 멤버들은 전부 직접 값을 할당해야 한다.
* enum 타입의 속성은 값으로 사용 가능하다.

```javascript
const a = Node.Mesh; // 0
const b = Node[Node.Mesh]; // 'Mesh'
```

* enum은 값 보다 타입으로 사용되는 경우가 더 많다.
  * 타입으로 사용하게 되면 멤버의 유니온과 비슷한 역할을 한다.

```typescript
// node: 'Mesh' | 'Texture' | 'Decal'
const logNode = (node: Node) => {
  console.log(Node[node]);
}
```

### 단점

* Enum은 아직 불안전하다.

```typescript
const logNode = (node: Node) => {}

logNode(Node.Mesh); 
logNode('Mesh'); // Error (node의 타입은 'Mesh' | 'Texture' | 'Decal' 이지만 에러 발생
```

* Enum을 사용하면 `Tree-shaking`이 되지 않는다.
  * JavaScript에 존재하지 않는 것을 구현하기 위해 TypeScript 컴파일러는 IIFE(즉시 실행 함수)를 포함한 코드를 생성하게 되는데  IIFE를 '사용하지 않는 코드'라고 판단할 수 없어서 tree-shaking이 일어나지 않는다

{% hint style="info" %}
**Tree-shaking**이란 사용하지 않는 코드를 삭제하는 기능을 말한다. 최종 번들 크기를 줄여 최적화 가능
{% endhint %}

{% hint style="info" %}
Enum 타입을 사용하되, 자바스크립트 코드로 생성되지 않게 하려면 **`const enum`** 을 사용하면 된다.
{% endhint %}

### 그렇다면 언제 사용해야 좋을까?

* 태그드 유니온(브랜딩)에 사용하면 좋다.
* 단, 같은 enum의 멤버여야 서로 구분된다. 다른 enum의 멤버끼리는 구분되지 않을 수 있다.

```typescript
enum Node {
  Mesh,
  Decal
}

interface MeshNode {
  type: Node.Mesh,
}

interface DecalNode {
  type: Node.Decal,
}

const MeshOrDecal = (node: MeshNode | DecalNode) => {
  if(node.type === Node.Mesh) {
    node; // MesNode
  } else {
    node; // DecalNode
  }
}
```
