[Typescript] Enum을 활용한 메소드 조건부 타이핑

HYUNGU, KANG·2020년 8월 4일
2

type SomeType<T extends "A">
=> type 선언부의 Generic 을 "A" 타입으로 사용하겠다.

type SomeType<T> = T extends "A" ? string : never;
=> SomeType 에 받은 Generic 이, "A" 라는 조건을 만족하면 string type, 아니라면 에러를 반환하겠다.

이 두가지와 Enum 을 활용해서 아래와 같이
Enum에 따라서 타입 추론이 되는 함수를 만들어 활용할 수 있다.

type UserData = {
    name: string;
    age: number;
    gender: "male" | "female";
};

type CartData = {
    items: Array<CartItem>;
    total: number;
    tax: number;
};
type CartItem = {
    title: string;
    amount: number;
    price: number;
    discountedPrice: number;
};

type PurchaseData = {
    purchases: Array<PurchaseItem>;
};
type PurchaseItem = {
    title: string;
    price: number;
    refunded: boolean;
};

enum API_TYPES {
    USER = "user",
    CART = "cart",
    PURCHASE = "purchase"
}

type ApiDataMap =
    | {
          type: API_TYPES.USER;
          data: UserData;
      }
    | {
          type: API_TYPES.CART;
          data: CartData;
      }
    | {
          type: API_TYPES.PURCHASE;
          data: PurchaseData;
      };

type ExtractDataType<Type extends API_TYPES, DataType> = DataType extends { type: Type; data: ApiDataMap["data"] }
    ? DataType["data"]
    : never;

const fetchItem = <T extends API_TYPES>(type: T): ExtractDataType<T, ApiDataMap> => {
    switch (type) {
        case API_TYPES.USER:
            return {
                name: "user",
                age: 19,
                gender: "male"
            } as any;
        case API_TYPES.CART:
            return {
                total: 0,
                tax: 0,
                items: []
            } as any;
        case API_TYPES.PURCHASE:
            return {
                purchases: []
            } as any;
        default:
            return null as any;
    }
};
const updateItem = <T extends API_TYPES>(type: T, item: Partial<ExtractDataType<T, ApiDataMap>>) => {
    // update logic
};


updateItem(API_TYPES.USER, { name: "bang9" });
updateItem(API_TYPES.CART, { name: "bang9" }); // Error
const userItem = fetchItem(API_TYPES.USER);
const cartItem = fetchItem(API_TYPES.CART);
const purchaseItem = fetchItem(API_TYPES.PURCHASE);

케이스가 좀 더 필요하다면 아래의 글도 참조하시라
https://velog.io/@bang9dev/Typescript-generic-with-function-logic

profile
JavaScript, TypeScript and React-Native

1개의 댓글

comment-user-thumbnail
2022년 4월 29일

감사합니다!

답글 달기