TypeScript의 Record란?
TypeScript의 Record란?
타입스크립트에서 타입 안정성을 도와주는 유틸리티 중 하나로 Record
가 있다. 객체 타입을 만들 때 쓰이는 도구로, Record<K,V>
형태로 코드에서 본 적이 있을 것이다.
Record의 기본 개념
Record<K, V>
- K: key 타입
- V: value 타입
Record는 각각의 Key에 대해 Value 값이 매핑된 객체를 만들어준다.
Record의 기본 예시
type UserRoles = Record<string, boolean>; // 모든 key가 string, value가 boolean 타입
const users: UserRoles = {
admin: true,
member: true,
guest: false
};
유니온 타입과 함께 활용하기
보통 실무에서는 유니온 타입과 함께 사용된다.
type User = 'admin' | 'member' | 'guest'; // 유니온 타입으로 제한된 유저 역할
type Permissions = Record<User, boolean>; // 유저 타입에 따라 허용범위를 제한하는 Permissions 정의
const permissions: Permissions = {
admin: true,
member: true,
guest: false
}; // User type에 없는 키를 추가하거나 누락할 때 컴파일 에러 발생
Record로 딕셔너리 만들기
Record
는 key-value로 구성되어 있기 때문에 딕셔너리를 구성할 때도 자주 활용된다.
/* 국제전화 국가번호 딕셔너리 */
type CountryCodes = Record<string, number>;
const countryCodes: CountryCodes = {
KR: 82,
US: 1,
FR: 33,
HK: 852
}
Record vs. 직접 객체 리터럴 작성하기
왜 굳이 Record를 써야 하지? 그냥 객체 리터럴을 바로 작성하면 되지 않나? 라고 생각할 수도 있다. 하지만 해당 객체를 활용해서 함수를 만들거나 값을 불러올 때, 키를 누락시키거나 오타가 발생하는 걸 미연에 방지할 수 있다.
Record를 사용했을 때
Key 타입을 User로 정하고 Value를 boolean으로 정한 Record 값을 사용했을 때이다.
함수 setupPermissions
에서 permissions 객체에 없는 키를 넣었을 때 바로 IDE에서 에러 표시를 해준다.
Record를 사용하지 않았을 때
객체 permissions를 Record를 사용하지 않고 객체 리터럴로 정의한 경우다.
setUpPermissions
에서 파라미터의 타입을 정의할 수 없기 때문에 any
로 처리되었고, 그 때문에 permissions
객체에 없는 키인 editor를 불러와도 컴파일에서는 에러를 감지하지 못한다. 런타임에서 코드가 다 돌아가고 나서야 에러를 발견하게 된다.
이렇게 레코드를 사용해서 객체 타입을 정의하면 미리 컴파일 단계에서 에러를 방지할 수 있고, 객체 키가 추가되거나 변경되었을 때도 손쉽게 추적해서 수정할 수 있다.
Partial, Required 유틸리티와 함께 활용하기
Partial
, Required
도 Record
와 마찬가지로 타입스크립트의 유틸리티 중 하나이다.
Partial
은 객체 값들을 모두 optional
값으로, Required
는 객체 값들을 모두 required
값으로 바꿔준다.
type User = 'admin' | 'member' | 'guest';
type PartialPermissions = Partial<Record<User, boolean>>;
const partialPermissions: PartialPermissions = {
admin: true
// member, guest 생략 가능
}
type User = 'admin' | 'member' | 'guest';
type RequiredPermissions = Required<Record<User, boolean>>;
const allPermissions: RequiredPermissions = {
admin: true,
member: true,
guest: false
// 모든 User 타입을 키로 사용해야 함
}