타입스크립트 - 유틸리티 타입

dobyming·2022년 12월 27일
0

Typescript Study

목록 보기
17/17

유틸리티 타입

유틸리티 타입은 필수 개념은 아니나, 후에 코드 유지보수성을 높여줄 수 있는 하나의 방법 중 하나입니다.

다음은 대표적인 유틸리티 타입 3가지 입니다.

1. Pick

선언한 타입들 중 일부만 사용하고 싶을때 사용합니다.

Usage : Pick<대상 type, '사용할 타입 나열~' | ' '>

interface Product {
    id: number;
    name: string;
    price: number;
    brand: string;
    stock: number;
}

// 1. 상품 목록을 받아오기 위한 API 함수
function fetchProducts(): Promise<Product[]> {
    //...
}

// interface ProductDetail {
//     id: number;
//     name: string;
//     price: number;
// }

// 2. 특정 상품의 상세 정보를 나타내기 위한 함수 
function displayProductDetail(shoppingItem: Pick<Product, 'id' | 'name' | 'price'>) {
    
}

shoppingItem 은 Product 중 id, name, price만 사용하고 싶을때 다음과 같이 Pick 예약어를 통해 일부만 가져다 쓸 수 있습니다.

이는 주석처리된 ProductDetail 인터페이스와 같은 작동방식을 지니며, 반복해서 쓸 필요없이 유지보수를 높여줍니다.

2. Omit

쓰지 않을 타입은 제외하고 나머지 타입들은 쓰겠다는 의도일때 사용합니다.

Usage : Omit<대상 type, '안 쓸 타입 나열~' | ' '>

3. Partial

선언된 타입들 중에서 일부의 상태값을 변화시키고 싶을때 주로 사용

Usage : Partial<type명>

interface UpdateProduct {
    id?: number;
    name?: string;
    price?: number;
    brand?: string;
    stock?: number;
}

// 3. 특정 상품 정보를 업데이트하는 함수 (UpdateProduct와 같은 매커니즘)
function updateProductItem(productItem: Partial<Product>) {
}

유틸리티 구현하기 - Partial

1. 일부 타입만 쓰겠다 ?: 구문 활용

interface userProfile {
    username: string;
    email: string;
    profilePhotoUrl: string;
}

 interface userProfileUpdate {
     username?: string;
     email?: string;
     profilePhotoUrl?: string
 }

이와 같이 표현할 수 있지만, 코드를 반복해서 사용하고 길어진다는 단점이 있습니다.

2. key-value로 접근

 type userProfileUpdate = {
     username?: userProfile['username'];
     email?: userProfile['email'];
     profilePhotoUrl?: userProfile['profilePhotoUrl'];
 }

3. mapped type

 type userProfileUpdate = {
     [p in 'username' | 'email' | 'profilePhotoUrl']?: userProfile[p]
 }

변수 p가 userProfile 인터페이스의 key값에 해당하는 부분을 반복문으로 돌며, 리턴 타입으로 value를 반환합니다.

4. keyof 활용

type userProfileKeys = {
    [p in keyof userProfile]?: userProfile[p]
}

3번 mapped type에서 유니온으로 선언된 key값들의 코드가 길어짐에 따라, keyof 예약어를 통해 코드를 간결하게 만들 수 있습니다.

결국 4번을 한번 더 리팩토링 시,

type Subset<T> = {
    [p in keyof T]?: T[p]
}

제네릭 타입으로 다양한 인터페이스를 받아오고 이는 곧 Partial 이 TS에서의 모듈화된 코드입니다.

+) Mapped type

type Heroes = 'Hulk' | 'Capt' | 'BlackWidow'
type HeroAges = { [H in Heroes]: number }

const ages: HeroAges = {
    Hulk : 33,
    Capt : 100,
    BlackWidow : '33' //리턴타입이 number가 아니므로 error code 
}

mapped type은 map함수와 비슷한 맥락에서, 반복문을 돌면서 각각의 값들의 타입을 전체 반영해준다는 의미로 이해할 수 있습니다.

0개의 댓글