keyof 타입 연산자
(이하 keyof 또는 keyof 연산자)는 객체 타입에서 객체의 키(프로퍼티)를 string 또는 number 리터럴 유니온 타입으로 생성하는 연산자입니다.
말로하면 잘 안와닿을 수 있기에 실제 코드를 하나 보면서 keyof
를 이해해봅시다.
type Member = {
id: number;
name: string;
};
type M = typeof Member; // type M = 'id' | 'name';
위 코드에서 typeof 연산자
는 Member
타입의 키인 'id', 'name'
을 추출하게 됩니다. 따라서 M
타입에는 'id' | 'name'
의 string 리터럴 유니온
타입이 정의되게 됩니다.
만약 타입에 인덱스 시그니쳐를 사용하고 있다면 keyof
는 키가 아닌 키의 타입을 따라가게 됩니다.
이때 인덱스 시그니쳐가 string
또는 number
타입일 때만 사용가능합니다.
type Languages = {
[lan: string]: string;
};
type L = keyof Languages; // type L = string | number;
type Numbers = {
[num: number]: number;
};
type N = keyof Numbers; // type N = number;
첫 번째 예시에서 L
의 타입이 string
이 아니라 number
인데요. 이런 일이 발생하는 원인은 TS 2.9 버전의 노트에 적혀있습니다.
Given an object type X, keyof X is resolved as follows:
- If
X
contains a string index signature, keyof X is a union of string, number, and the literal types representing symbol-like properties, otherwise- If
X
contains a numeric index signature, keyof X is a union of number and the literal types representing string-like and symbol-like properties, otherwisekeyof X
is a union of the literal types representing string-like, number-like, and symbol-like properties.간단히 요약하자면 객체 X를 주었을 때 문자열 인덱스 시그니쳐는 문자열/숫자/리터럴/심볼과 같은 프로퍼티 포함하는 합집합 타입이 되고, 숫자 인덱스 시그니쳐는 숫자/리터럴/ 문자열, 심볼과 같은 프로퍼티를 나타내는 합집합 타입 이라는 것 입니다.
그리고 이 원인은 자바스크립트의 동작과 관련이 있는데, 자바스크립트는 객체를 해석할 때 숫자를 문자열로 변환하기 때문이라고 합니다. (즉, "0"와 0는 같다고 봄)
만약 이런 일을 방지하고 싶다면 컴파일러 설정(tsconfig)
를 설정하는 방법이 있습니다.
{
"compilerOptions": {
(...)
"keyofStringsOnly": true,
},
}
설정 전
설정 후