Menu

TypeScript 유틸리티 타입 총정리: 전체 목록과 예제

TypeScript에 내장된 유틸리티 타입을 한곳에 모았습니다. Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ReturnType, Awaited, 문자열 타입 등 각각 한 줄 설명과 실행 가능한 예제를 담았습니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

유틸리티 타입은 TypeScript에 내장된 제네릭 타입으로, 한 타입을 다른 타입으로 바꿉니다. 모든 필드가 선택적인 User 타입을 하나 더 쓰는 대신 Partial<User>라고 쓰고, 필드 세 개를 복사하는 대신 Pick<User, "id" | "name">이라고 씁니다. 전역 타입이므로 import가 필요 없습니다.

User가 바뀌면 파생된 네 타입도 모두 따라 바뀝니다. TypeScript 표준 라이브러리(lib.es5.d.ts)에는 유틸리티 타입이 22개 선언되어 있습니다. 아래 섹션에서는 다루는 타입의 종류별로 모두 정리하고, 자세한 페이지가 있으면 링크를 달았습니다.

객체 타입: Partial, Required, Readonly, Pick, Omit, Record

유틸리티 타입하는 일예시
Partial<T>모든 속성을 선택적으로 만든다업데이트 페이로드용 Partial<User>
Required<T>모든 속성을 필수로 만든다(? 제거)기본값을 적용한 뒤의 Required<Config>
Readonly<T>모든 속성을 readonly로 만든다Readonly<State>
Pick<T, K>키 K만 남긴다Pick<User, "id" | "name">
Omit<T, K>키 K를 제거한다Omit<User, "password">
Record<K, V>키가 K, 값이 V인 객체 타입Record<"en" | "de", string>

Required<T>는 Partial<T>의 반대입니다. Partial 페이지에서 둘 다 다루며, 이런 스프레드가 통과시키는 명시적 undefined 문제도 설명합니다.

유니언 타입: Exclude, Extract, NonNullable

유틸리티 타입하는 일예시
Exclude<U, M>M에 대입 가능한 유니언 멤버를 제거한다Exclude<"a" | "b" | "c", "a">는 "b" | "c"
Extract<U, M>M에 대입 가능한 유니언 멤버만 남긴다Extract<string | number, number>는 number
NonNullable<T>null과 undefined를 제거한다NonNullable<string | null>은 string

이 세 가지는 객체가 아니라 유니언에 동작합니다. 객체 타입과 그 키 목록을 받는 Pick, Omit과의 핵심 차이가 바로 이것입니다.

함수와 클래스 타입: Parameters, ReturnType 등

유틸리티 타입하는 일예시
ReturnType<F>함수 타입의 반환 타입ReturnType<typeof createStore>
Parameters<F>매개변수 타입을 튜플로Parameters<typeof fetchPage>[0]
ConstructorParameters<C>클래스 생성자의 매개변수를 튜플로ConstructorParameters<typeof Point>
InstanceType<C>생성자가 만드는 인스턴스 타입InstanceType<typeof Point>
ThisParameterType<F>함수의 this 매개변수 타입ThisParameterType<typeof greet>
OmitThisParameter<F>this 매개변수를 뺀 함수 타입greet.bind(obj)의 타입
ThisType<T>객체 리터럴 메서드 안의 this 타입을 정한다빌더 API에서 noImplicitThis와 함께 사용
NoInfer<T>이 위치에서 타입 매개변수가 추론되지 않게 막는다fallback: NoInfer<C>

이 유틸리티들은 타입을 받는데 createOrder는 값이므로 typeof createOrder가 필요합니다. 클래스도 마찬가지입니다. typeof Point는 생성자 타입이고, 타입 자리에 쓴 Point는 이미 인스턴스 타입을 뜻합니다.

NoInfer는 제네릭이 타입을 어디서 가져올지 제어합니다.

NoInfer가 없으면 TypeScript는 두 인수 모두에서 C를 추론해 "red" | "green" | "blue"로 넓히므로, fallback의 오타가 그대로 통과합니다.

문자열 타입: Uppercase, Lowercase, Capitalize, Uncapitalize

유틸리티 타입하는 일예시
Uppercase<S>문자열 리터럴 타입을 대문자로Uppercase<"get">은 "GET"
Lowercase<S>소문자로Lowercase<"GET">은 "get"
Capitalize<S>첫 글자를 대문자로Capitalize<"name">은 "Name"
Uncapitalize<S>첫 글자를 소문자로Uncapitalize<"Name">은 "name"

이 네 가지는 TypeScript로 작성된 것이 아니라 컴파일러에 내장되어 있으며, 이벤트 핸들러 이름을 만드는 `on${Capitalize<E>}`처럼 템플릿 리터럴 타입 안에서 가장 유용합니다.

Promise: Awaited

유틸리티 타입하는 일예시
Awaited<T>중첩된 Promise를 풀어 await로 얻는 타입Awaited<Promise<Promise<number>>>는 number

Awaited<ReturnType<typeof fn>>은 async 함수의 결과 타입을 따로 선언하지 않고 이름 붙이는 표준 방법입니다.

유틸리티 타입 조합하기

유틸리티 타입은 중첩할 수 있습니다. 자주 나오는 조합 몇 가지는 외워 둘 만합니다.

중첩된 유틸리티 타입은 안쪽부터 읽습니다. Readonly<Pick<Post, "id" | "title">>는 먼저 속성 두 개를 남기고, 그다음 읽기 전용으로 만듭니다. 같은 부품으로 일부 키만 선택적으로 만드는 PartialBy 헬퍼도 만들 수 있으며, Partial 페이지에 구현이 있습니다.

유틸리티 타입은 런타임에 아무것도 하지 않는다

모든 유틸리티 타입은 컴파일할 때 지워집니다. Omit<User, "password"> 타입의 값도 원래 객체에 password가 있었다면 런타임에 그대로 가지고 있을 수 있습니다.

타입은 코드가 무엇을 읽을 수 있는지만 제한합니다. 데이터에서 필드를 제거하려면 마지막 줄처럼 구조 분해로 떼어 내고, 런타임 변경을 막으려면 Readonly가 아니라 Object.freeze를 쓰세요. 내장 타입은 한 줄짜리 매핑된 타입과 조건부 타입이므로, 같은 도구로 직접 만들 수도 있습니다.

자주 묻는 질문

TypeScript에서 유틸리티 타입이란 무엇인가요?

TypeScript에 기본으로 들어 있으며 다른 타입을 변환하는 제네릭 타입입니다. Partial<T>는 모든 속성을 선택적으로 만들고, Pick<T, K>는 일부 속성만 남기고, ReturnType<F>는 함수의 반환 타입을 가져옵니다. 표준 라이브러리에 선언되어 있으므로 아무것도 import하지 않고 씁니다.

유틸리티 타입을 import해야 하나요?

아니요. Partial, Omit, Record, ReturnType 등은 TypeScript 내장 라이브러리 파일에 있는 전역 타입입니다. 어디서든 Partial<User>라고 쓰면 되고, import도 npm 패키지도 필요 없습니다.

TypeScript에 내장된 유틸리티 타입은 무엇인가요?

모두 lib.es5.d.ts에 선언된 22개입니다: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ConstructorParameters, ReturnType, InstanceType, ThisParameterType, OmitThisParameter, ThisType, NoInfer, Awaited, Uppercase, Lowercase, Capitalize, Uncapitalize.

유틸리티 타입이 런타임에 객체를 바꾸나요?

아니요. 타입만 설명하며 JavaScript 출력에서는 지워집니다. Omit<User, "password">는 password 속성을 삭제하지 않고, Readonly<T>는 아무것도 동결하지 않습니다. 실제 객체를 바꾸려면 구조 분해 나머지 패턴, Object.freeze 같은 코드를 직접 써야 합니다.

유틸리티 타입을 직접 만들 수 있나요?

네. 내장 유틸리티 타입도 평범한 TypeScript이며, 대부분 lib.es5.d.ts에 있는 한 줄짜리 매핑된 타입이나 조건부 타입입니다. type Nullable<T> = { [K in keyof T]: T[K] | null }도 같은 방식으로 쓴 사용자 정의 유틸리티 타입입니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기