내일배움캠프 TIL (230129): enum을 타입 별칭(type alies)의 키에 사용하기

Jiumn·2023년 1월 29일
0

스파르타에서 준 타입스크립트 enum 퀴즈를 풀어보며 또 한번 타입스크립트 기초가 부족하다는 걸 깨달았다. 문제를 풀면서 고민하고 배운 점들을 의식의 흐름대로 정리해보고자 한다.

enum을 타입 별칭(type alies)의 키에 사용하기

  1. 다음을 충족하는 타입을 완성하고 inventory 객체에 타입을 반영하세요.
    Car enum 사용 필수.
    string 키 사용 금지.
enum Color {
  Red,
  Blue,
  Black,
}

enum Car {
  Sedan,
  Truck,
  Coupe,
}
type Inventory = {}; // 객체 내부에 Car enum 사용해서 지정해야 함

const inventory: Inventory = {
  Sedan: "Red",
  Truck: "Black",
};

inventory 객체의 key인 Sedan과 Truck을 Car enum에 해당하는 값으로 쓰도록 타입을 지정해야 한다.


인덱스 시그니처의 한계

처음에는 enum의 키를 동적으로 가져오기 위해 인덱스 시그니처([key:Car])를 사용하려고 했지만 인덱스 시그니처는 string, number, symbol, Template literal만 가능하다.

in 연산자 사용하기

두 번째 방법으로 [key in Car]를 적용해봤지만 에러가 발생한다.

Object literal may only specify known properties, and 'Sedan' does not exist in type 'Inventory'.


결론: keyof typeof 연산자 사용하기

결론적으로 Enum 값을 객체의 키로 사용하고 싶으면 keyof typeof을 사용하면 된다.

keyof은 객체의 키를 유니언 타입으로 변경해주는 typescript 연산자다.
(✅ js에는 keyof이 없다!)

enum에서는 keyof을 단독으로 사용할 수 없고 typeof과 함께 써야(=keyof typeof) 키를 유니언 타입으로 변경해서 객체에 사용할 수 있다.

(참고: 타입스크립트 핸드북)

그러나 여전히 의문이 남아 있었는데... 🤔


왜 keyof이 아닌 keyof typeof을 써야 할까?

자세한 설명을 아래 stackOverflow에서 찾았다!

스택오버플로우의 답변에 의하면 다음과 같다.
(참고: What does "keyof typeof" mean in TypeScript?)

typeof 연산자는 자바스크립트와 타입스크립트에서 다르게 작동한다.

type Language = 'EN' | 'ES'; 
const userLanguage: Language = 'EN';
const preferences = { language: userLanguage, theme: 'light' };

console.log(typeof preferences); // "object"
type Preferences = typeof preferences; 
// type '{language: 'EN''; theme: string; }'

위의 예시를 보면 자바스크립트에서는 typeof 연산자의 결과로 object가 반환된다.
타입스크립트에서는 preference 객체의 형태 그대로가 반환된다는 것을 알 수 있다.

여기서 enum의 특성을 알아야 한다❗

enum은 런타임 상태에서 구체적인 타입이 아닌 object로 취급된다는 점이다.

따라서 자바스크립트로 런타임되기 전 타입스크립트 상태에서 typeof 연산자를 통해 enum이 가진 구체적인 객체 타입으로 변환해야 한다. 그리고 나서 타입스크립트의 keyof 연산자를 적용해야 enum의 key 값들을 리터럴 유니온으로 가져올 수 있게 된다.

이것이 바로 enum의 키를 불러오기 위해 keyof typeof 연산자를 써야하는 내 나름의 해석이다. (틀린 점이 있다면 댓글로 알려주세요!)

type Inventory = {
  [key in keyof typeof Car]?: keyof typeof Color;
};

const inventory: Inventory = {
  Sedan: "Red",
  Truck: "Black",
};

keyof typeof 연산자를 붙인 후에는 in 연산자를 포함해서 Car 객체의 모든 키를 열거하도록 한다.

inventory의 키에는 Car의 모든 키가 포함되어 있지 않으므로 옵셔널 프로퍼티 문법인 ?를 붙여준다.

profile
Back-End Wep Developer. 꾸준함이 능력이다. Node.js, React.js를 주로 다룹니다.

0개의 댓글