Typescript 일부 prop만 추출해서 사용하기 - Extract, Extends, Partial, Omit, Exclude

Jeenie·2024년 7월 17일
0

타입스트립트

목록 보기
4/4

아래와 같은 데이터 타입이 있다.

포괄적인 Schedule 데이터, 그 중 일부만을 사용하는 PremiumSchedule 데이터.

Schedule에는 있는 타입을 PremiumSchedule는 모두 사용하지만 그 중 일부는 사용하지 않는다.

타입을 일부만 추출해서 사용하는 5가지 방법을 알아보자.

1. 그대로 분리해서 사용하기

두가지 문제가 있다

  1. 전혀 멋지지 않다
  2. 타입 중복 선언

이런식으로 타입을 늘려가다 타입 수정요청이 들어온다면 감당할 수 없을 것이다.

2. Extends

export interface PremiumSchedule {
  startTime: number;
  startDate: Date;
  endTime: number;
  endDate: Date;
}
export interface Schedule extends PremiumSchedule {
  season: number;
  premiumOn: boolean;
}

가장 간단한 해결책. 하지만 나의 상황에는 의미가 맞지 않았다.
이 데이터 구조상 Schedule은 더 포괄적인 데이터이고, 그 중 PremiumSchedule이 특별한 데이터이다.
하지만 이 코드를 처음보는 개발자는 "Premium이 기본값이고 Schedule이 특별한 거구나"라고 생각할 것이다.

의미가 반대가 되는 상황에서는 사용하기 좋을 것 같다.

3. Partial

Schedule 타입 중 일부만 사용하겠다고 명시.

  const {
    mutateAsync: getPremiumData,
    data,
    isPending,
  } = useGetScheduleData<Partial<Schedule>>();

모든 타입이 옵셔널이 되었다.
하지만 나는 모든 타입이 옵셔널하다는 것을 명시하려는 것이 아니었다.

이 코드를 처음보는 개발자는 "PremiumSchedule 데이터는 다 옵셔널하구나"라고 생각할 것이다.
Premium에는 seasonpremium만이 없다는 것만을 명확히 해야한다.

여전히 두가지 문제가 있다

  1. 멋지지 않다
  2. 명확하지 않다

4. Extract

Schedule이라는 타입을 사용할 건데, 그 중에서 이 타입만 사용할거라고 명시하기.

  const {
    mutateAsync: getPremiumData,
    data,
    isPending,
  } = useGetScheduleData<
    Extract<
      Schedule,
      { startTime: number; startDate: Date; endTime: number; endDate: Date }
    >
  >();

이 코드를 처음 보는 개발자도 해당 타입만 사용한다는 것을 알 수 있다.
하지만 이것도 너무 길고, 타입이 중복된다.

여전히 두가지 문제가 있다
1. 멋지지 않다
2. 타입이 중복된다

5. Omit

Schedule이라는 타입을 사용할 건데, 그 중에서 이 두가지를 제외한 타입을 사용하겠다고 명시한다.

  const {
    mutateAsync: getPremiumData,
    data,
    isPending,
  } = useLeaderboardTools<Omit<Schedule, "season" | "premium">>();

Typescript가 내 의도대로 타입 추론을 하고 있다.
이 코드를 처음보는 개발자 또한 Schedule이 공통적인 형태이지만, Premium에는 seasion과 premium이 없구나 라고 생각할 수 있을 것이다.

6. Exclude

Omit과 비슷하게 동작하지만 쓰이는 경우가 다르다.
Omit은 위와 같이 객체에서 특정 프로퍼티를 제거하는 타입.

하지만 내가 제외하려는 타입이 유니온 타입이라면?

유니온 타입이란?
A || B

type SocialProvider = 'google' | 'discord' | 'apple' | 'facebook'; // union type

type NewRecord = Record<Omit<SocialProvider, 'apple'>, string>;
// Error: Type 'Omit<"google" | "discord" | "apple" | "facebook", "apple">' does not satisfy the constraint 'string | number | symbol'.ts(2344)

따라서 Omit의 key로는 유니온 타입을 넘길 수 없다.
아래처럼 사용해야한다.

type SocialProvider = 'google' | 'discord' | 'apple' | 'facebook';

type NewRecord = Record<Exclude<SocialProvider, 'apple'>, string>;
profile
Web Front-end developer

0개의 댓글

관련 채용 정보