My Boundary As Much As I Experienced

타입에러 해결법) Property Chaining이 깊을 때 필요한 속성만 타입 단언 해주는 법 본문

FrontEnd/TypeScript

타입에러 해결법) Property Chaining이 깊을 때 필요한 속성만 타입 단언 해주는 법

Bumang 2024. 6. 7. 14:22

문제점

아래처럼 특정 에러 시 에러 메시지를 표출해주려 했는데

타입스크립트가 errorResponse.data의 타입을 추론해내지 못했다.

      let errorResponse = (error as AxiosError).response;
      if (errorResponse?.status === 400) {
        // 'errorResponse.data' is of type 'unknown'.ts(18046)
        Alert.alert("알림", errorResponse.data.message);
        dispatch(orderSlice.actions.rejectOrder(item.orderId));
      }

 

'뭐 대강 최종 속성인 message는 string이겠지?' 싶어서 message 다음에 as string을 넣어도

errorResponse.data is of type 'unknown'이란 에러는 사라지지 않는다.

// 여전히 'errorResponse.data' is of type 'unknown'.ts(18046)는 사라지지 않는다.
Alert.alert("알림", errorResponse.data.message as string);

 

어떻게 타입 단언을 하여 타스가 알아먹게 만들까?..

 

해결법: 어떤 식으로 타입 구조가 잡혀있는지 먼저 파악하자 (라이브러리 내 복잡한 타입이라도..)

먼저 Axios의 타입을 까봤다. 내가 파악해야될 타입은 AxiosError.response.message의 타입이다.

그래서 AxiosError를 먼저 까봤다.

export class AxiosError<T = unknown, D = any> extends Error {
  constructor(
      message?: string,
      code?: string,
      config?: InternalAxiosRequestConfig<D>,
      request?: any,
      response?: AxiosResponse<T, D>
  );

  config?: InternalAxiosRequestConfig<D>;
  code?: string;
  request?: any;
  response?: AxiosResponse<T, D>;
  isAxiosError: boolean;
  status?: number;
  toJSON: () => object;
  cause?: Error;
  ...
}

 

AxiosError를 보면 message가 속성으로 있는게 보인다.

그러나 나는 AxiosError.message가 아니라

AxiosError.response.data.message을 찾아야 하므로 response를 찾아봐야했다.

 

response는 AxiosResopnse<T, D>라고 한다.

또 다른 타입으로 둘러쌓여 있는 상태였다.

  response?: AxiosResponse<T, D>;

 

 

내 직관 상 T가 실제 데이터이고 D는 세부 설정 값이었던거 같은데...

하여튼 AxiosResponse 타입도 찾아본다.

export interface AxiosResponse<T = any, D = any> {
  data: T;
  status: number;
  statusText: string;
  headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
  config: InternalAxiosRequestConfig<D>;
  request?: any;
}

 

AxiosResponse<T, D>에서 예측대로 data부분은 T이고, config부분이 D이다.

그렇다면 data에 해당하는 제네릭 T엔 어떤 데이터들이 있을까?

(사실 그건 백엔드 개발자 분에게 물어봐야하는 영역이다..)

 

 

하여튼 그건 중요하지 않다. 왜냐하면 data 안의 모든 컬럼들을 설명해주지 않아도 되기 때문이다.

아래처럼 data부분만 구조분해할당하여 message컬럼만 뽑을 수 있기 때문이다.

모든 타입을 알아내서 설명해줄 필요가 없다. 

        Alert.alert(
          "알림",
          (errorResponse as AxiosResponse<{message: string}>).data.message,
        );

 

하여튼 message만 구조분해할당하여 string으로 지정해주고 해결하였다.

 

 

마치며

타입스크립트 실력이 꽤 올라간거 같다.

취준 땐 내가 쓰는 라이브러리의 복잡한 타입 까보는 것을 무서워했는데

현재는 라이브러리를 까보며 나에게 필요한 타입이 무엇인지 알아낼 수 있게 되었다.