조건부 타입과 맵드 타입, 유틸리티 타입

2023. 3. 15. 10:04·프론트엔드/JavaScript, TypeScript

조건부 타입

조건부타입이란 입력된 제네릭 타입에 따라 타입을 결정하는 타입이다.

type Condition<T> = T extends A ? B : C

위 타입은 T가 A에 할당 가능하면 타입은 B가 되고 그렇지 않으면 C가 된다.

조건부 타입을 활용해서 아래와 같이 타입 판별을 하는 타입을 구현할 수 있다.

type IsString<T> = T extends string ? true : false

분산 조건부 타입

T extends A 에서 T(제네릭이)가 유니온 타입인 경우 조금 다르게 작동한다.

해당 타입이 A에 할당가능한지를 검사하지 않고 유니온의 각 요소가 A에 할당가능 한지를 검사한다

type Exclude<T, U> = T extends U ? T : never
/// 예시: type A = Exclude<'a' | 'b' | 'c', 'a'> 

아래 예시의 경우에 'a' | 'b' | 'c'가 'a'에 할당가능한지 검사하는게 아니라

유니온 타입의 각 요소 'a', 'b', 'c'가 각각 'a'에 할당 가능한지를 검사하고

그 결과들을 다시 유니온으로 묶어서 타입을 만든다.

이 때 never들은 제외하고 유니온으로 묶는다.

따라서 타입 A는 'b' | 'c' 로 추론된다.

분산 조건부 타입을 활용해서 유틸리티 타입인 Exclude나 맵드 타입과 결합해서 Pick등을 구현할 수 있다.

type Exclude<T, U> = T extends U ? T : never
type Pick<T, K extends keyof T> = {
  [P in K] : T[P]
}

infer의 활용

조건부 타입에서 extends 뒤에 infer를 활용할 수 있다.

제네릭의 타입을 추론하고 추론한 타입을 ? 뒤에서 활용이 가능하다

T extends infer U ? U : T

이를 활용해서 함수의 리턴타입이나 파라미터 타입을 구할 수 있다.

type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer Args) => any ? Args : T
type ReturnType<T> = T extends (...args: any) => infer Return ? Return : T

맵드 타입

맵드 타입은 어떤 타입을 다른 타입으로 변환해주는 것이다.

함수형 프로그래밍의 맵의 타입버전 이라고 생각하면 된다.

type Readonly<T> = {
    readonly [P in keyof T]: T[P]
}

위처럼 객체 타입의 각 속성들을 readonly로 바꿔주거나,

type Partial<T> = {
    [P in keyof T]?: T[P]
}

각 속성들을 선택적으로 바꿔주는 타입을 만들 수 있다.

indexable타입과 비슷한 모양이지만 대괄호 안에 [P in keyof T] 가 들어있다.

먼저 keyof T는 T(객체)의 key들을 유니온 형태로 반환한다.

in연산자는 해당 유니온의 각 요소들을 순회한다.

이를 활용해서 객체의 각 속성에 새로운 타입을 주거나, readonly , ?를 줄 수 있다.

-를 활용해서 붙어있는 readonly, ? 을 뗄 수도 있다.

type NoReadonly<T> = {
    -readonly [P in keyof T]: T[P]
}
type NoQuestion<T> = {
    [P in keyof T]-?: T[P]
}

유틸리티 타입

위에서 구현해본 ReadOnly, Partial, Parameters, ReturnType, Pick, Exclude 등은 TS에서 유틸리티 타입으로 제공한다.

일일이 구현할 필요 없이 만들어진 유틸리티 타입들을 가져다 쓰면 더 편하다.

저작자표시 (새창열림)

'프론트엔드 > JavaScript, TypeScript' 카테고리의 다른 글

동시 여러 개의 토큰 리프레시 요청 관리하기  (0) 2024.07.28
Typescript와 Duck typing  (0) 2023.12.11
타입 가드  (1) 2023.01.25
?. - Optional chaining 연산자 / ?? - Null 병합 연산자  (0) 2022.08.22
Promise 일정 시간 초과시 대기 취소하고 에러 처리하기  (1) 2022.08.07
'프론트엔드/JavaScript, TypeScript' 카테고리의 다른 글
  • 동시 여러 개의 토큰 리프레시 요청 관리하기
  • Typescript와 Duck typing
  • 타입 가드
  • ?. - Optional chaining 연산자 / ?? - Null 병합 연산자
정현우12
정현우12
  • 정현우12
    정현우의 개발 블로그
    정현우12
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 프론트엔드 (56)
        • JavaScript, TypeScript (12)
        • 스타일링 (1)
        • React (13)
        • Next.js (4)
        • 개발 환경 (9)
        • 테스트 (3)
        • 성능 최적화 (11)
        • 함수형 프로그래밍 (2)
        • 구조 (1)
      • 프로젝트 회고 (23)
        • 이미지편집기 개발 (7)
        • 엑셀 다운로드, 업로드 공통 모듈 개발 (4)
        • 사용자 매뉴얼 사이트 개발 (3)
        • 통계자동화 솔루션 개발 (1)
        • 엑셀 편집기 개발 (5)
        • API 플랫폼 (1)
        • 콜센터 솔루션 OB 캠페인 (1)
        • AI 스튜디오 (1)
      • 백엔드 (0)
  • 블로그 메뉴

    • 홈
    • 포트폴리오
    • 태그
  • 인기 글

  • 태그

    memoization
    webpack
    useReducer
    엑셀
    Next.js
    React-boilerplate
    커스텀 훅
    TypeScript
    엑셀 에디터
    React
    사용자 매뉴얼 사이트
    웹 성능 최적화
    Github Actions
    렌더링 성능 최적화
    frontend
    로딩 성능 최적화
    JavaScript
    라이브러리 선정
    이미지 편집기
    회고
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정현우12
조건부 타입과 맵드 타입, 유틸리티 타입
상단으로

티스토리툴바