본문 바로가기
프로그래밍/typescsript

타입스크립트의 Enums (이넘)

by 한코코 2022. 11. 23.

Enum(이넘)이란?

특정 값들의 집합을 의미하는 자료형이며, 타입스크립트에서는 문자형 이넘과 숫자형 이넘을 지원한다.

 

 

 

 

 

숫자형 이넘

숫자형 이넘을 선언할때 초기값을 주면 차례로 1씩 증가한다.

만약 초기값을 주지않으면 초기값이 0으로 자동지정되며 역시 1씩 증가한다.

enum Direction {
  Up = 1,
  Down, // 2
  Left, // 3
  Right // 4
}

 

숫자형 이넘을 사용하는 예

enum Response {
  No = 0,
  Yes = 1,
}

function respond(recipient: string, message: Response): void {...}
respond("Captain Pangyo", Response.Yes);

 

숫자형 이넘에서 주의할 점

다른 이넘 타입의 값을 사용하면 선언하는 이넘의 첫번째 값에 초기화를 해줘야 한다는 점이다.

초기화를 해주지 않으면 초기값이 0부터 시작하는 숫자형 이넘으로 자동으로 적용되기때문인가?

enum Wrong {
  A = getSomeValue(),
  B, // Error, 초기화가 필요합니다.
}

 

 

 

 

 

문자형 이넘

숫자형 이넘과 개념적으로 거의 비슷하지만, 런타임에서 미세한 차이가 있다. (타입스크립트 공식 참조사이트)

문자형 이넘은 숫자형 이넘과 다르게 auto-incrementing이 없다.

대신 초기화 당시 값을 모두 입력하기때문에 문자형 이넘은 항상 명확한 값이 나온다.

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

 

 

 

 

 

복합 이넘

문자형과 숫자형을 혼합해서 생성하는 이넘이지만 타입스크립트 공식 사이트는 이 방식을 권고하지 않는다.

enum BooleanLikeHeterogeneousEnum {
    No = 0,
    Yes = "YES",
}

 

 

 

 

 

런타임 시점에서의 이넘 특징

이넘은 런타임시 실제 객체 형태로 존재합니다.

enum E { X, Y, Z }

// 객체형태기 때문에 obj 타입을 사용할 수 있다.
function getX(obj: { X: number }) {
  return obj.X;
}
getX(E); // 이넘 E의 X는 숫자이기 때문에 정상 동작

 

 

 

컴파일 시점에서의 이넘 특징

이넘이 런타임 시점에서는 실제 객체지만 keyof를 사용할때 주의해야 합니다. 일반적으로 keyof를 사용해야 하는 상황에서는 대신 keyof typeof를 사용해야한다.

 

keyof란?

객체 타입에서 객체의 키 값들을 숫자나 문자열 리터럴 유니언을 생성한다. 아래 타입 Psms "x"|"y"와 동일한 타입.

type Point = { x: number; y: number };
type P = keyof Point;
// type P = keyof Point

type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish;
// type A = number (unknown은 생략됨)

type Mapish = {[k: string]: boolean};
type M = keyof Mapish;
// type M = string | number;
// 자바스크립트 객체키는 항상 문자열을 강제하기때문에 obj[0]은 obj["0"]과 동일한걸 기억하자

 

typeof란?

자바스크립트에서 해당 변수가 어떤 타입인지 사용해본 적이 있는 유형연산자다.

let s = "hello"
console.log(typeof(s));
------------------------
> string

 

그냥 typeof만 사용할경우, 이넘 객체 자체를 타입으로 받아들이지만

keyof를 사용할경우, keyof가 객체의 키값들을 뽑아서 배열로 만들어주기때문에 편하게 다중 타입을 사용할 수 있다. (참조블로그)

 

 

실제로 사용하는 코드

enum LogLevel { ERROR, WARN, INFO, DEBUG }

// 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
type LogLevelStrings = keyof typeof LogLevel;

function printImportant(key: LogLevelStrings, message: string) {
  const num = LogLevel[key];
  if (num <= LogLevel.WARN) {
    console.log('Log level key is: ', key);
    console.log('Log level value is: ', num);
    console.log('Log level message is: ', message);
  }
}
printImportant('ERROR', 'This is a message');
-----------------------------------------------------------------
> Log level key is:  ERROR
> Log level value is:  0
> Log level message is:  This is a message

 

 

 

 

리버스 매핑

숫자형 이넘에만 존재하는 특징이며 에넘의 키로 값을 얻을 수 있고, 값으로 키를 얻을 수도 있다.

enum Enum { A }
  
let a = Enum.A; // 키로 값을 획득 하기
let keyName = Enum[a]; // 값으로 키를 획득 하기
console.log(a, keyName)
-------------------------------------------
> 0 A

댓글