본문 바로가기
source-code/TypeScript

JsToTs : axios

by mattew4483 2023. 8. 21.
728x90
반응형

JavaScript를 TypeScript로 변환하기🦾

 

2023.01.14 - [BTY/TypeScript] - JsToTs : 비동기 처리 - Promise

 

JsToTs : 비동기 처리 - Promise

JavaScript를 TypeScript로 변환하기🦾 비동기 처리 유저 정보를 받아오는 비동기 처리 함수를 생각해보자. 기존 JS 코드는 다음과 같다. const getUserProfile = async ({ id }) => { let config = { method: "get", url: `${U

233life.tistory.com

유저 정보를 조회하는 비동기 요청을 TS로 변환했었다.

 

interface UserInfo {
  id: number;
  name: string;
}

const getUserProfile = async ({ id }: { id: number }): Promise<UserInfo> => {
  let config = {
    method: "get",
    url: `${URL}/auth/profile/${id}`,
  };

  try {
    const _res = await axios.get(`${URL}/auth/profile/${id}`);
    return _res.data;
  } catch (e) {
    throw e;
  }
};

이때 axios 라이브러리를 사용해 http 요청 및 응답을 처리했다.

 

Axios란?
브라우저와 node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리

const _res = await axios.get(`${URL}/auth/profile/${id}`) ← axios의 리턴값으로 Promise가 반환됨을 예상할 수 있다.

그런데 문제, 여기서 _res의 타입이 뭐길래... 아래 줄인 _res.data 에서 아무런 에러가 나지 않는 걸까??

 

TS가 추론한 _res의 타입은 AxiosResponse라는 interface임을 확인할 수 있다.

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

AxiosResponse의 정의!

아하... AxiosResponse는 data, status, statusText 등의 속성을 가진 interface였다!

 

이때 첫 번째 제네릭으로 넘겨준 타입은 → 응답값의 data에 해당하는 타입을 의미한다.

따라서...

interface UserInfo {
  id: number;
  name: string;
}

export const getUserProfile = async ({ id }: { id: number }) => {
  try {
    const _res: AxiosResponse<UserInfo> = await axios.get(`${URL}/auth/profile/${id}`);
    return _res.data;
  } catch (e) {
    throw e;
  }
};

다음과 같이 작성해 줘도 getUserProfile 함수의 리턴값의 타입이 Promise<UserInfo>로 추론 가능해진다!

 

얼레. 그렇다면 axois.get은 뭐길래 AxiosResponse 타입을 알아서 리턴하는 걸까?

export class Axios {
  constructor(config?: AxiosRequestConfig);
  defaults: AxiosDefaults;
  interceptors: {
    request: AxiosInterceptorManager<AxiosRequestConfig>;
    response: AxiosInterceptorManager<AxiosResponse>;
  };
  getUri(config?: AxiosRequestConfig): string;
  request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
  get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  delete<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  head<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  options<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  postForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  putForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  patchForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
}

그냥 Axios class 전체를 가져왔다.

이 중 우리가 궁금한 get 메서드의 리턴값을 살펴보면...

Promise<R>을 리턴하는데,

R이란 제네릭은 R=AxiosResponse<T>, 즉 AxiosResponse interface에 T 제네릭을 넘겨준 타입을 뜻하며,

T는 get 메서드의 첫 번째 제네릭을 의미한다.

 

아하! 그렇다면...

interface UserInfo {
  id: number;
  name: string;
}

export const getUserProfile = async ({ id }: { id: number }) => {
  try {
    const _res = await axios.get<UserInfo>(`${URL}/auth/profile/${id}`);
    return _res.data;
  } catch (e) {
    throw e;
  }
};

다음과 같이 get 메서드에 응답 값의 데이터 타입인 UserInfo를 제네릭으로 넘겨줘 사용할 수도 있겠다!

_res.data의 타입이 UserInfo로 잘 추론됨도 확인 가능!

728x90
반응형