TypeScriptSTUDY _ 5장 . 타입 활용하기 [ 5.1 조건부 타입 | 5.2 탬플릿 리터럴 타입 활용하기 ]

zeroha·2024년 12월 6일
0

TypeScriptStudy

목록 보기
14/32
post-thumbnail

5.1 조건부 타입

  • 조건부 타입(삼항연산자와 동일): Condition ? A : B 형태.
    Condition이 true면 A, 아니면 B를 반환.

  • 조건부 타입의 장점
    : 중복 코드를 제거하고 상황에 맞는 타입을 설정 가능.
    : 더 정확한 타입 설계에 도움.
    .
    .
    .

1. extends와 제네릭을 활용한 조건부 타입

  • extends 키워드: 조건부 타입에서 특정 타입을 확장하거나 제약 조건을 설정할 때 사용.
T extends U ? X : Y

T가 U를 확장하면 X, 아니면 Y를 반환.

interface Bank {
  financialCode: string;
  companyName: string;
  name: string;
  fullName: string;
}
  
interface Card {
  financialCode: string;
  companyName: string;
  name: string;
  appCardType: string;
}

type PayMethod<T> = T extends "card" ? Card : Bank;
type CardPayMethodType = PayMethod<"card">; // Card 타입 반환
type BankPayMethodType = PayMethod<"bank">; // Bank 타입 반환

extends와 조건부 타입 활용 시, 특정 조건에 따라 이 인터페이스를 포함하거나 제외 가능.


2. 조건부 타입을 사용하지 않았을 때의 문제점

:중복된 코드가 발생하고 API 엔드포인트 관리가 어려움.

( API 엔드포인트 )

/baeminpay/.../bank → 은행 정보 반환.
/baeminpay/.../card → 카드 정보 반환.
/baeminpay/.../appcard → 앱 카드 정보 반환.

API 엔드포인트: 계좌, 카드, 앱카드의 결제 수단 정보를 배열 형태로 반환.
API 엔드포인트가 비슷하기 때문에 서버 응답 처리 공통 함수 생성
-> 해당 함수에 타입을 전달 - 타입별로 처리 로직 구현

  • React Query와 조건부 타입

    • useQuery를 사용한 커스텀 훅:useGetRegisteredList
      -> useQuery의 반환 값을 돌려줌.

    • fetcherFactory: Axios를 래핑해주는 함수.

    • 서버에서 데이터를 가져오고 onSuccess 콜백 함수를 거친 결곽값을 반환.

      type PayMethodType = PayMethodInfo<Card> | PayMethodInfo<Bank>;
      
      export const useGetRegisteredList = (
        type "card" | "appcard" | "bank"
      ): UseQueryResult<PayMethodType[]> => {
        const url = `baeminpay/codes/${type === "appcard" ? "card" : type}`;
        
        const fetcher = fetcherFactory<PayMethodType[]>({
          onSuccess: (res) => {
            const usablepocketlist =
      				 res?.filter(
            (pocket : PocketInfo<Card> | PocketInfo<Bank>) =>
              pocket?.useType === "USE"
            ) ?? [];
           return usablePocketList;
          },
        });
        
        const result = useCommonQuery<PayMethodType[]>(url, undefined, fetcher);
        
        return result;
      };
    • useGetRegisteredListtype에 따라 데이터를 반환:

      • "card" ,"appcard" , "bank" -> 해당 결제 수단의 결제 수단 정보 리스트를 반환.
      • 하지만 함수의 인자가 올바르지 않은 경우, 타입스크립트가 정확한 타입을 추론하지 못함.
    • useGetRegisteredList가 반환하는 Data타입은 PocketInfo<Card> | PocketInfo<Bank>

    • 타입 설계가 유연하지 않아(유니온으로 되어있어서),
      타입스크립트가 전달된 데이터에 따라 반환 타입(Data)을 명확히 추론하지 못함.

-> 결론 : 인자에 다라 반환되는 타입을 다르게 설정, extends를 사용한 조건부 타입을 활용 : 반환 타입을 동적으로 설정.


3. extends 조건부 타입을 활용하여 개선하기

  • useGetRegisteredList 함수는 입력된 타입("card", "appcard", "bank")에 따라 데이터를 반환하지만, 함수의 반환 타입을 명확히 추론하기 어려움.
  • 잘못된 타입 입력 시에도 에러를 즉시 잡아내지 못할 가능성이 있음.
type PayMethodType<T extends "card" | "appcard" | "bank"> = T extends 
	| "card" 
	| "appcard" 
	? Card
 	| Bank;

결제 수단 타입 : "card", "appcard", "bank"만 들어올 수 있기 때문에 extends를 한정자로 활용 -> 제네릭에 넘겨오는 값 제한

외의 값 입력 시 컴파일 에러 발생.

타입 안정성 향상:

useGetRegisteredList("card") → PocketInfo 타입 자동 추론.
useGetRegisteredList("bank") → PocketInfo 타입 자동 추론.

조건부 타입을 활용하면 가독성 및 유지보수성 개선:

  • 중복 코드 제거.
    -> API 변경 시 조건부 타입만 수정하면 전체 코드 반영 가능.

  • extends 활용 예시

    1. 제네릭과 extends를 함께 사용해 제네릭으로 받는 타입 제한
      -> 개발자는 잘못된 값을 넘길 수 없기 때문에 휴먼 에러 방지
    2. extends를 활용해 조건부 타입 설정
      -> 조건부 타입 사용 - 반환 값을 사용자가 원하는 값으로 구체화
      -> 불필요한 타입 가드, 타입 단언 등을 방지

4. infer를 활용해서 타입 추론하기

  • extends를 사용할 때 infer('추론하다') 키워드 사용 : 타입을 추혼하는 역할
    -> 삼항연산자를 가용한 조건문의 형태

그러면, extends로 조건을 서술 -> infer로 타입을 추론


5.2 탬플릿 리터럴 타입 활용하기

typescript에서는 유니온 타입을 사용 -> 변수 타입을 특정 문자열로 지정

 type HeaderTag = "h1" | "h2" | "h3" | "h4" | "h5";

컴파일타입의 변수에 할당되는 타입을 특정 문자열로 정확하게 검사 -> 휴먼 에러 방지
자동완성기능 -> 개발 생산성을 높일 수 있음.

  • typescript 4.1부터 확장 방법인 템플릿 리터럴 타입 Template Literal Type을 지원
    : 템플릿 리터럴 타입은 자바스크립트의 템플릿 리터럴 문법 사용 -> 특정 문자열에 대한 타입을 선언하는 기능
  • HeaderTag ( 템플릿 리터럴 타입을 사용 )
 type HeadingNumber = 1 | 2 | 3 | 4 | 5;
 type HeaderTag = `h${HeadingNumber}`;
  • 템플릿 리터럴 타입을 사용 -> 더욱 읽기 쉬운 코드로 작성 가능
  • 코드 재사용 / 수정 용이

주의 ) 타입스크립트 컴파일러가 유니온을 추론하는데 시간이 오래걸리면 비효율적
-> 타입스크리브가 타입을 추론하지 않고 에러를 내뱉을 때가 있음.
결론 : 템플릿 리터럴 타입에 삽입된 유니온 조합의 경우의 수가 너무 많지 않게 적절하게 나누어 타입을 정의하는 게 좋다.

.
.
.


도서참조 : 우아한 타입스크립트 with 리액트

profile
하 영

0개의 댓글

관련 채용 정보