타입스크립트/고급 타입

유틸리티 타입

webmaster 2022. 10. 18. 09:07
728x90

유틸리티 타입은 이미 정의해 놓은 타입을 변환할 때 사용하기 좋은 타입 문법입니다. 유틸리티 타입을 꼭 쓰지 않더라도 기존의 인터페이스, 제네릭 등의 기본 문법으로 충분히 타입을 변환할 수 있지만 유틸리티 타입을 쓰면 훨씬 더 간결한 문법으로 타입을 정의할 수 있습니다.

Pick

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

//상품 목록을 받아오기 위한 API 함수
function fetchProducts(): Promise<Product[]> {
    const products:Product[] = [];
    return new Promise(function (resolve) {
        resolve(products);
    });
}

/*
interface ProductDetail {
    //product를 재활용 할 수 없다 -> product 의 일부지만, 새로 인터페이스를 만들어야한다
    id: number;
    name: string;
    price: number;
}

function displayProductDetail(shoppingItem: ProductDetail) {
    //목록에 있는 데이터가 모두 있는것은 아니다 -> 인터페이스 모양이 다를 수 있다.

}
 */
type ShoppingItem = Pick<Product, 'id' | 'name' | 'price'>

function displayProductDetail(shoppingItem: ShoppingItem) {
    //Pick을 사용하여, 재활용이 필요한 타입만 꺼낼 수 있다.
}
  • Product에 일부분만 필요한 ProductDetail을 인터페이스로 만들어야 한다.
    • 이는 코드 중복을 야기하며, 인터페이스를 매번 만드는 것은 효율적이지 않다.
  • Pick을 사용하면, 필요한 속성 값만 추출하여, 타입을 만들 수가 있다.
    • Pick< 추출해야 할 인터페이스, 추출 프로퍼티>

Omit

interface AddressBook {
    name: string;
    phone: number;
    address: string;
    company: string;
}
const phoneBook: Omit<AddressBook, 'address'> = {
    name: '재택근무',
    phone: 12342223333,
    company: '내 방'
}
const chingtao: Omit<AddressBook, 'address'|'company'> = {
    name: '중국집',
    phone: 44455557777
}
  • 오밋(Omit) 타입은 특정 타입에서 지정된 속성만 제거한 타입을 정의해 준다
  • Pick과 반대로 제거해야 할 대상을 2번째 파라미터에 작성한다
    • Omit<제거해야 할 인터페이스, 제거하는 프로퍼티>

Partial

partial 타입은 특정 타입의 부분집합을 만족하는 타입을 정의할 수 있다.

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

//특정 상품 정보를 업데이트(갱신 )하는 함수 (patch 메서드)
//Product를 파라미터로 받게 되면, 필요한 것만 입력받아 업데이트를 할 수없다.
function updateProductItem(productItem: UpdateProduct) {

}
 */
type UpdateProduct = Partial<Product> //Partial를 사용하면, Product을 속성을 모두 옵셔널로 받게 된다.
function updateProductItem(productItem: UpdateProduct) {

}
  • 수정 목록을 받기 위해서, 새로운 인터페이스를 선언한 뒤, 내부 프로퍼티들의 옵셔널로 선언해 주어야 한다.
    • 중복 코드를 야기한다.
  • Partial을 사용하면, 내부 프로퍼티를 옵셔널로 받을 수 있는 타입이 선언된다.
    • Partial<인터페이스> 로 내부 속성을 옵셔널로 받을 수 있다.

유틸리티 타입 구현하기(Partial)

//#1
type UserProfileUpdate = {
    username?: UserProfile['username']; //위에 정의된 속성을 그대로 사용할 수 있다
    email?: UserProfile['email'];
    profilePhotoUrl?: UserProfile['profilePhotoUrl'];
}

//#2
type UserProfileUpdate2 = {
    [p in 'username' | 'email' | 'profilePhotoUrl']?: UserProfile[p] //맵드 타입이라고 한다
}

//#3
//type UserProfileKeys = keyof UserProfile
type UserProfileUpdate3 = {
    [p in keyof UserProfile]?: UserProfile[p]
}

//#4 -> 모든 타입이 가능하도록 적용(partial)
type Subset<T> = {
    [p in keyof T]?: T[p]
}
  • #1: 인터페이스의 타입을 그대로 사용하면서, 옵셔널만 추가했다.
  • #2: 인터페이스의 프로퍼티를 in 문을 사용하여, 한 줄로 줄였다 
  • #3: in 뒤에 나오는 부분들이 해당 인터페이스의 keyof 값이기 때문에, 더 간략하게 줄일 수 있다.
  • #4: 모든 타입을 받을 수 있도록 제네릭을 사용하였다 -> Partial과 같아진다
728x90

'타입스크립트 > 고급 타입' 카테고리의 다른 글

ES6 최신 문법  (0) 2022.10.22
JS에 TS 적용하기  (0) 2022.10.18
맵드 타입  (0) 2022.10.18