Prettify 타입으로 복잡한 타입 쉽게 보기

김상민·2025년 8월 17일
0

복잡한 제네릭 타입들을 중첩해서 쓰다 보면 결과 타입이 뭔지 도저히 알 수가 없다.

Omit<Pick<SomeType, 'a' | 'b'> & OtherType, 'c'>

IDE에서 보면 이런 식으로 나와서 매번 최종 타입까지 찾아가서 봐야한다.

그러던 중에 유튜브 영상에서 이런 헬퍼 타입을 만들어서 사용하는 방법을 보게 되었다.


/**

 * @description 복잡한 교차/중첩 타입을 펼쳐서 읽기 쉽게 표시하는 헬퍼 타입

 * 타입의 의미는 그대로 유지하면서, IDE에서 보기 좋은 형태로 변환한다.

 */

export type Prettify<T> = {

  [K in keyof T]: T[K]

} & {}

사용 예시


// Before: 복잡한 타입

type Complex = Omit<{ a: string; b: number; c: boolean }, 'c'> & { d: Date }

// IDE에서 "Omit<{...}, 'c'> & { d: Date }" 로 표시됨



// After: Prettify 적용

type Clean = Prettify<Complex>

// IDE에서 "{ a: string; b: number; d: Date }" 로 깔끔하게 표시됨



// 유니온 타입도 잘 동작함

type PolicyCategories = Prettify<NonNullable<PoliciesSearch['category']> | '전체'>

// IDE에서 "일자리" | "주거" | "금융" | "교육" | "전체" 로 깔끔하게 표시됨

동작 원리

타입을 "예쁘게" 만들어주는 마법 같은 느낌이어서 원리를 찾아봤다.

1. Mapped Type으로 재구성


{ [K in keyof T]: T[K] }

이 부분이 TypeScript에게 "T의 모든 키를 순회하면서 새로운 객체 타입을 만들어라"라고 지시한다. 교차 타입이나 복잡한 조건부 타입을 단일 객체 리터럴로 재구성하는 역할이다.

2. 빈 교차 타입으로 강제 평가


& {}

이게 핵심이다. 빈 교차 타입을 추가하면:

  • TypeScript 컴파일러가 타입을 즉시 평가하도록 강제함

  • 지연 계산을 방지하고 타입 캐시를 무효화함

  • 내부 표현을 사용자가 읽기 쉬운 형태로 정규화함

왜 타입스크립트는 알아서 이렇게 안해줄까?

AI의 답변은 다음과 같다.

TypeScript는 성능을 위해 복잡한 타입 계산을 가능한 한 미루려고 한다. 그래서 IDE에서 보면 Omit<Pick<...>, '...'> & {...} 같은 내부 표현 그대로 보여준다.

Prettify는 이런 지연 계산을 강제로 실행시켜서 최종 결과를 보여주는 방식이다.

언제 사용하면 좋을까?

  • 여러 제네릭 타입을 조합해서 만든 복잡한 타입

  • 유니온 타입이 복잡하게 중첩된 경우  

  • 라이브러리 타입들을 조합해서 만든 커스텀 타입

  • 동료들이 타입을 이해하기 쉽게 만들고 싶을 때

타입을 볼 때 타입 선언부까지 가지 않고 확인할 수 있어서 좋은 것 같다. 이렇게 타입 계산을 강제로 시키는 방식이 IDE에서 성능을 실제로 떨어뜨리는지는 확인해볼 필요가 있다.

참고

https://youtu.be/q5DFpyIN5Xs?si=qhd1vV67EOa4w5MI&t=241

profile
성장하는 웹 프론트엔드 개발자 입니다.

0개의 댓글