공통 타입 변환을 위한 유틸리티 타입
타입스크립트에서 제공하는 유틸리티 타입(Utility Types)은 type, interface를 입맛에 맞게 사용할 수 있도록 도와주는 유용한 기능이다.
유틸리티 타입의 종류는 다음 그림과 같이 매우 많다(타입스크립트 공식 페이지).

이 중 사용 빈도가 잦은 Partial, Pick, Omit, Record, Readonly에 대해 알아보자.
1. Partial
partial은 ‘부분적인’이라는 뜻으로, 정의된 타입의 속성을 모두 옵셔널로 사용하여 부분적으로 원하는 속성만 사용하도록 할 수 있다.
우선 Partial의 정의는 다음과 같다.
type Partial<T> = {
[P in keyof T]?: T[P];
};
Partial<Type>의 방식을 통해 속성을 옵셔널하게 사용하며, 예시는 다음과 같다.
interface Hardware{
cpu: string;
gpu: string;
memory: number;
storage: number;
accessary: string;
}
const selectOptions = (default: Hardware, selected: Partial<Hardware>) => {
setOptions({...default, ...selected});
};
const defaultOption = {
cpu: "M1";
gpu: "10-core";
memory: 16;
storage: 512;
accessary: "Touch ID";
}
const selectedOption = {
cpu: "M2";
memory: "32";
storage: "1024";
}
이와 같은 방법으로 사용하지 않는 속성을 옵셔널로 변경하여 사용할 수 있다.
2. Pick
pick은 ‘뽑다’는 뜻으로, 정의된 타입에서 속성을 지정하여 사용할 수 있다.
Pick의 정의는 다음과 같다.
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Pick<Type, Keys>의 방식을 사용해 사용할 속성을 문자열이나 유니온 타입으로 Keys에 지정하여 해당 속성만 사용한다.
interface Exercise{
title: string;
type: string;
time: number;
complete: boolean;
}
type BriefExercise = Pick<Exercise, "title" | "complete">;
const today = {
title: "jogging";
complete: true;
}
Partial은 모든 속성을 옵셔널로 사용하지만 Pick은 속성을 지정하여 필요한 타입만 정의하는 방식으로 사용한다.
3. Omit
omit은 ‘생략하다’라는 뜻으로, 정의된 타입에서 생략할 속성을 지정하여 사용할 수 있다.
Omit의 정의는 다음과 같다.
type Omit<T, K extends keyof any> = {
[P in Exclude<keyof T, K>]: T[P]
}
Omit<Type, Keys>의 방식으로 사용하며, Pick과 반대로 필요하지 않은 타입을 지정하여 정의하는 방식으로 사용한다.
interface Exercise{
title: string;
type: string;
time: number;
complete: boolean;
}
type BriefExercise = Omit<Exercise, "type" | "time">;
const today = {
title: "jogging";
complete: true;
}
Pick과 Omit의 용도는 같지만 정의 방법은 상반된다.
정의된 타입에서 생략하고 싶은 속성이 많을 때는 Pick, 생략하고 싶은 속성이 적을 때는 Omit을 사용하면 효과적이다.
4. Record
record는 ‘기록하다’는 뜻으로, key-value 세트를 생성하여 사용할 수 있다.
Record의 정의는 다음과 같다.
type Record<K extends string, T> = {
[P in K]: T;
};
Record<Keys, Type>의 방식으로 사용하며, 두 개의 타입에서 한 타입을 Keys, 한 타입을 Type으로 조합하여 사용할 수 있다.
type MacBookType = "air13" | "air15" | "pro13" | "pro14" | "pro16";
interface Performance{
cpu: string;
memory: number;
storage: number;
};
const OnTheMarket: Record<MacBookType, Performance> = {
air13: { cpu:"M1", memory:8, storage: 256 };
air15: { cpu:"M2", memory:16, storage: 512 };
pro13: { cpu:"M2", memory:16, storage: 1024 };
pro14: { cpu:"M2 pro", memory:32, storage: 1024 };
pro16: { cpu:"M2 ultra", memory:96, storage: 2048 };
}
위와 같은 방식으로 두 타입을 조합해서 사용할 수 있다.
5. Readonly
readonly는 ‘읽기 전용’이므로 타입을 읽기 전용으로 정의하여 사용할 수 있다.
Readonly의 정의는 다음과 같다.
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
타입을 사용해 readonly 속성을 부여하고 싶은 경우에 사용할 수 있다.
interface LimitSize{
size: number;
}
const myData: Readonly<LimitSize> = {
size: 32;
}
myData.size = 64; // error









