유틸리티 타입은 Typescript에서 매우 유용한 기능이고 기존 타입을 변형해 새로운 타입을 만들수 있게 해준다.
코드 재사용성을 높이고, 불필요한 타입 정의를 줄여줍니다. 아래 코드에서 유틸리티 타입에 대해 심도있게 살펴봅시다.
상품의 기본 정보를 정의
interface Product {
id: number;
name: string;
price: number;
brand: string;
stock: number;
something: object;
}
function fetchProduct(): Promise<Product[]> {
// ...
}
function productDetail(shoppingItem: Pick<Product, 'id' | 'name' | 'price'>) {
// ...
}
// interface ProductDetail {
// id: number;
// name: string;
// price: number;
// }
Pick 유틸리티 타입을 사용하여 Product 인터페이스에서 id, name, price 속성만 선택
Pick<Product, 'id' | 'name' | 'price' 은 ProductDetail과 동일한 형태의 타입을 생성
Product라는 타입들이 목록에서 쓰이고, 상세정보에서 그대로 활용되기 어려울 때 Pick이라는 유틸리티 타입을 가지고 변환해서 사용할 수 있다 이걸 유틸리티 타입이라고 하며 커뮤니케이션에서는 제네릭 타입이라고도 얘기 한다
type UpdateProduct = Partial<Product>
function updateProductItem(productItem: Partial<Product>) {
// ...
}
Partial 유틸리티 타입을 사용해 Product 인터페이스의 모든 속성을 선택적으로 만듬
이는 업데이트할 때 모든 속성을 필수로 제공할 필요 없이, 일부 속성만 업데이트할 수 있게함
interface UserProfile {
username: string;
email: string;
profilePhotoUrl: string;
}
// 첫 번째 정의 방식
type UserProfileUpdate = {
username?: UserProfile['username']
email?: UserProfile['email']
profilePhotoUrl?: UserProfile['profilePhotoUrl']
}
// 두 번째 정의 방식 (축약) Mapped Type
type UserProfileUpdate = {
[p in 'username' | 'email' | 'profilePhotoUrl']?: UserProfile[p]
}
// 세 번째
type UserProfileKeys = keyof UserProfile
type UserProfileUpdate = {
[p in keyof UserProfile]?: UserProfile[p]
}
// 네 번째 최정적으로 Partial을 구현 해보면 제네릭 사용
type Subset<T> = {
[p in keyof T]?: T[p]
}
요약
유틸리티 타입을 사용하면 기존의 타입을 변형해 새로운 타입을 쉽게 생성할 수 있고 주요 유틸리티 타입으로는 Partial, Pick, Omit 등이 있으며 이들은 코드의 가독성, 유지보수성을 높여준다 제네릭과 맵드 타입을 함께 사용하면 더욱 강하고 유연한 타입정의가 가능