[TypeScript 기본 이론] #6 Enums(열거형)

mechaniccoder·2020년 7월 6일
0

TypeScript 기본이론

목록 보기
6/6
post-thumbnail

열거형은 이름이 있는 상수들의 집합을 정의할 수 있다. 무슨 소리인지 아래 읽다보면 알 것이다. 기본적으로 TS는 숫자와 문자열 기반 열거형을 제공한다.

Numeric enums


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()는 상수가 아닌 계산된 멤버이다.

String enums


문자열 열거형은 숫자형 열거형과는 달리 문자열로 초기화해야 한다.

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

Heterogeneous enums(이종 열거형)


숫자와 문자를 섞어 열거형을 만들 수는 있지만 굳이 그렇게 할 필요가 없다고 docs에서 말하고 있다.

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

Computed and constant members


상수라고 간주하는 경우는 다음과 같다.

  1. 문자, 숫자 리터럴로 만들었을 때
  2. 상수 열거형 멤버를 참조할 때
  3. 상수 열거형 표현식을 괄호로 묶었을 때
  4. +, =, ~ 와 같은 단항 연사자를 사용할 때
  5. +, =, *, /, %, <<, >>, >>>, &, |, ^와 같은 이중 연사자를 사용할 때
enum FileAccess {
    // 상수 멤버
    None, // 0
    Read    = 1 << 1, // 항목 5번에 해당
    Write   = 1 << 2, // 항목 5번에 해당
    ReadWrite  = Read | Write, // 항목 2, 5번에 해당
    // 계산된 멤버
    G = "123".length
}

Union enums and enum member types


열거형의 모든 멤버가 리터럴일 경우 특이한 점이 있다.

열거형 멤버를 타입처럼 사용할 수 있다.

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의 값 둘 중 하나를 가질 것이다.

Enums at compile time


열거형이 런터임에 존재하는 실제 객체이지만 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');

Reverse mappings


숫자 열거형 멤버는 name → value 말고 value → name 과 같은 역 매핑도 가능하다. 한 마디로 값을 이용해 키를 찾는다는 말이다.

enum Test {
    A
}
let a = Test.A; // a = 0
let nameOfA = Test[a]; // "A"

문자형 열거형은 역 매핑할 수 없다. 기억하자.

const enums


상수를 이용한 열거형을 쓰고 싶을 때는 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는 이미 존재하는 열거형의 타입을 묘사하기 위해 사용된다. 일반적인 열거형에서는 상수 멤버뒤에 초기화되지 않은 멤버가 있다면 이 멤버를 상수로 간주한다. 그러나 ambient enums에서는 초기화되지 않는 멤버를 항상 계산된 멤버로 간주한다. (declare를 사용한다.)

declare enum Enum {
    A = 1,
    B, // 비-ambient enums에서는 상수, ambient enums에서는 계산된 멤버!
    C = 2
}

References


https://typescript-kr.github.io/pages/enums.html TypeScript HandBook

profile
세계 최고 수준을 향해 달려가는 개발자입니다.

0개의 댓글