1. TypeScript > partial 과 intersection type 사용해서 유니온타입 대신 타입단언하기
- 상황에 따라서..useInfiniteQuery 를 사용한 훅의 반환값이 반환되거나 useQuery 를 사용한 훅의 반환값이 반환되어야 하는 훅이 있었다.
- 주의할점은, infiniteQuery 를 사용해도 useQuery 의 data 값처럼 접근가능하도록 infiniteQuery 의 데이터를 가공했고, 반환타입역시 아래와 같이 가공해놓은 상태이다. 즉, useQuery 와 useInfiniteQuery의 반환값이 거의 동일하고, 일부 useInfniteQuery 에만 있는 반환값들 (Ex. fetchNextPage, hasNextPage..등등)만 달랐다.
// MEMO: UseInfiniteQueryResult 의 data 타입은 UseQueryResult 와 동일하게 맞추도록 커스텀 2024.7.17 문희
export type CustomUseInfiniteQueryResult<T> = Omit<UseInfiniteQueryResult<T, ApiError>, 'data'> & {
data: T;
};
- 물론 useInfniteQuery 사용처에서도 select 옵션을 사용하여 가공해놓았다
select: (response) => {
return {
data: response.pages.flatMap((page) => page.data),
pageable: response.pages.flatMap((page) => page.pageable),
pages: [],
pageParams: [],
};
},
-
암튼! 이렇게 타입을 지정해놓으니 useInfiniteQuery 의 반환타입은 useQuery의 반환타입을 일부 상속받는 형태와 같았다.
-
따라서 , 케이스에 따라서 useCombinedHook(가칭) 에서 useInfiniteQuery 반환값을 반환하거나 useQuery의 반환값을 반환해도 잘 사용하겠거니 생각했으나..당연히 유니온타입(
UseQueryResult | UseInfiniteQueryResul
)으로 잡아버리니 useInfiniteQuery에만 포함되어있는 반환값에 접근하지 못했다. -
그래서 해결방법은 아래와 같다. 즉 UseQueryResult 와 CustomUseInfiniteQueryResult 타입을 인터섹션 타입으로 묶어주고, 다만 CustomUseInfiniteQueryResult 타입을 전부 partial 로 묶어주어, 옵셔널하게 받는 타입을 하나 만들고 이걸로 타입 단언을 해버리는 것이다..허허
type CombinedQueryResult = UseQueryResult<PaginatedCatalogsData, ApiError> &
Partial<CustomUseInfiniteQueryResult<PaginatedCatalogsData>>;
- 결국 타입단언을 하는 것은 아쉽지만 아예
any
로 단언하거나partial
없이 단언하는 것 보다는 안전하다고 생각한다.