열거형은 이름이 있는 상수들의 집합을 정의할 수 있다. 무슨 소리인지 아래 읽다보면 알 것이다. 기본적으로 TS는 숫자와 문자열 기반 열거형을 제공한다.
enum Direction {
Up = 1,
Down,
Left,
Right,
}
이렇게 Up=1
로 초기화하면 Down=2, Left=3, Right=4
의 값을 가진다. 아래처럼 초기화하지 않아도 된다.
enum Direction {
Up,
Down,
Left,
Right,
}
이러면 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가 계산된 멤버이므로 초기화가 필요합니다.
}
초기화되지 않은 열거형이 먼저 나왔나? getSomeValue()
로 초기화 된 멤버 이후이다.
상수로 초기화된 열거형 이후인가? getSomeValue()
는 상수가 아닌 계산된 멤버이다.
문자열 열거형은 숫자형 열거형과는 달리 문자열로 초기화해야 한다.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
숫자와 문자를 섞어 열거형을 만들 수는 있지만 굳이 그렇게 할 필요가 없다고 docs에서 말하고 있다.
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
상수라고 간주하는 경우는 다음과 같다.
+, =, ~
와 같은 단항 연사자를 사용할 때+, =, *, /, %, <<, >>, >>>, &, |, ^
와 같은 이중 연사자를 사용할 때enum FileAccess {
// 상수 멤버
None, // 0
Read = 1 << 1, // 항목 5번에 해당
Write = 1 << 2, // 항목 5번에 해당
ReadWrite = Read | Write, // 항목 2, 5번에 해당
// 계산된 멤버
G = "123".length
}
열거형의 모든 멤버가 리터럴일 경우 특이한 점이 있다.
enum ShapeKind {
Circle,
Square,
}
interface Circle {
kind: ShapeKind.Circle; // kind 프로퍼티는 ShapeKind의 Circle 멤버의 값을 가져야한다.
radius: number;
}
interface Square {
kind: ShapeKind.Square; // kind 프로퍼티는 ShapeKind의 Square 멤버의 값을 가져야한다.
sideLength: number;
}
let c: Circle = {
kind: ShapeKind.Square, // 오류! 'ShapeKind.Circle' 타입에 'ShapeKind.Square' 타입을 할당할 수 없습니다.
radius: 100,
}
enum E {
Foo,
Bar,
}
function f(x: E) {
if (x !== E.Foo || x !== E.Bar) {
// ~~~~~~~~~~~
// 에러! E 타입은 Foo, Bar 둘 중 하나이기 때문에 이 조건은 항상 true를 반환합니다.
}
}
x
매개변수의 타입은 E
이기 때문에 Foo
또는 Bar
의 값 둘 중 하나를 가질 것이다.
열거형이 런터임에 존재하는 실제 객체이지만 keyof
키워드는 일반적인 객체와는 다르게 동작한다.
enum LogLevel {
ERROR, WARN, INFO, DEBUG
}
/**
* 이것은 아래와 동일합니다. :
<유니온 형식>
* type LogLevelStrings = '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');
숫자 열거형 멤버는 name → value
말고 value → name
과 같은 역 매핑도 가능하다. 한 마디로 값을 이용해 키를 찾는다는 말이다.
enum Test {
A
}
let a = Test.A; // a = 0
let nameOfA = Test[a]; // "A"
문자형 열거형은 역 매핑할 수 없다. 기억하자.
상수를 이용한 열거형을 쓰고 싶을 때는 const
를 앞에 붙이자. 이러면 계산된 멤버를 가질 수 없다.
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
// 이는 컴파일됐을 때 아래와 같다.
var directions = [0, 1, 2, 3];
ambient enums
는 이미 존재하는 열거형의 타입을 묘사하기 위해 사용된다. 일반적인 열거형에서는 상수 멤버뒤에 초기화되지 않은 멤버가 있다면 이 멤버를 상수로 간주한다. 그러나 ambient enums에서는 초기화되지 않는 멤버를 항상 계산된 멤버로 간주한다. (declare
를 사용한다.)
declare enum Enum {
A = 1,
B, // 비-ambient enums에서는 상수, ambient enums에서는 계산된 멤버!
C = 2
}
https://typescript-kr.github.io/pages/enums.html TypeScript HandBook