enum
키워드를 사용해 정의할 수 있다.enum Direction {
Up = 1, // 1로 초기화된 숫자 열거형을 선언
Down, // 뒤 따르는 멤버들은 자동으로 증가된 값을 갖는다. 2
Left, // 3
Right, // 4
}
// 전부 초기화 하지 않을 수도 있다.
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right,// 3
}
enum Response {
No = 0,
Yes = 1,
}
function respond(recipient: string, message: Response): void {
// ...
}
respond("Princess Caroline", Response.Yes)
enum E {
A = getSomeValue(),
B, // 오류 : 앞에 A가 계산된 멤버여서 초기화가 필요하다.
계산된 멤버와 상수 멤버
각 열거형의 멤버는 상수거나, 계산된 값일 수 있다.
상수로 간주하는 경우
enum E { X }
에서 E.X는 상수이다.
초기화 값이 없고, 숫자 상수로 초기회된 열거형 멤버 뒤에 따라나오는 경우 앞에 나온 상수 값에 1씩 증가한 값을 상수로 갖는다.enum E1 { X, Y, Z } enum E2 { A = 1, B, C } // 'E1' 과 'E2' 의 모든 열거형 멤버는 상수입니다.
열거형 멤버는 상수 열거형 표현식으로 초기화된다.
상수 열거형 표현식은 컴파일 시 알아낼 수 있는 TS 표현식의 일부입니다.
상수 열거형 표현식
1. 리터럴 열거형 표현식 (기본적으로 문자 또는 숫자 리터럴)
2. 이전에 정의된 다른 상수 열거형 멤버에 대한 참조 (다른 열거형에서 시작될 수 있음)
3. 괄호로 묶인 상수 열거형 표현식
4. 상수 열거형 표현식에 단항 연산자+, -, ~
를 사용한 경우
5. 상수 열거형 표현식을 이중 연산자+, -, *, /, %, <<, >>, >>>, &, |, ^
의 피연산자로 사용할 경우
상수 열거형 표현식 값이NaN
이거나Infinity
이면 컴파일 시점에 오류가 난다.
이 외 다른 모든 경우 열거형 멤버는 계산된 것으로 간주한다.enum FileAccess { // 상수 멤버 None, Read = 1 << 1, Write = 1 << 2, ReadWrite = Read | Write, // 계산된 멤버 G = "123".length }
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
런타임에서 열거형
열거형은 런타임에 존재하는 실제 객체이다.enum E { X, Y, Z } // 실제로 아래와 같이 함수로 전달될 수 있다. function f(obj: { X: number }) { return obj.X; } // E가 X라는 숫자 프로퍼티를 가지고 있기 떄문에 동작하는 코드이다. f(E);
이종 열거형
기술적으로 문자열과 숫자열 열거형을 섞을수 있지만 굳이 그렇기 할 이유가 없다.
JS 런타임에서 장점을 취하려 것이 아니라면, 권장 안한다.enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", }
-
가 적용된 경우 (-1, -100)enum ShapeKind {
Circle,
Square,
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
let c: Circle = {
kind: ShapeKind.Square, // ShapeKind.Square 형식은 ShapeKind.Circle 형식에 할당할 수 없다.
radius: 100,
}
enum E {
Foo,
Bar,
}
function f(x: E) {
if (x !== E.Foo || x !== E.Bar) {
// x가 E.Foo가 아닌지 확인한다. true면? || 이후 조건은 체크 할 필요가 없음
// 만약 조건이 false면? x는 E.Foo이기 때문에 E.Bar가 아닌지 묻는것은 적절하지 않다.
// 에러! E 타입은 Foo, Bar 둘 중 하나이기 때문에 이 조건은 항상 true를 반환합니다.
}
}
keyof typeof
키워드를 사용하면 모든 열거형의 키를 문자열로 나타내는 타입을 가져온다.enum LogLevel {
ERROR, WARN, INFO, DEBUG
}
type LogLevelStrings = keyof typeof LogLevel;
function printImportant(key: LogLevelStrings, messsage: 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 messsage is : ', messsage);
}
}
printImportant('ERROR', 'This is a messsage');
enum Enum {
A
}
let a = Enum.A;
let nameOfA = Enum[0];
// 👆 이 예제는 JS코드로 컴파일 하면
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[0];
// 👆 이렇게 컴파일 된다.
name
-> value
) 매핑과 역방향(value
-> name
)매핑 두 정보를 모두 저장하는 객체로 컴파일 된다. 다른 열거형 멤버 참조는 항상 프로퍼티 접근으로 노출 되고 인라인되지 않는다.const
열거형const enum Enum {
A = 1,
B = A * 2
}
const enum Directions {
Up,
Down,
Left,
Right
}
let direction = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
// 위의 ts 파일은 아래 js 파일로 컴파일 된다.
var direction = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
declare enum Enum {
A = 1,
B,
C = 2
}
ambient 열거형 VS 비-ambient 열거형
비-ambient 열거형: 초기화되지 않은 멤버가 상수로 간주하는 멤버 뒤에 있다면, 이 멤버도 상수로 간주한다.
ambient 열거형: 초기화되지 않은 멤버는 항상 계산된 멤버로 간주한다.