JavaScript를 TypeScript로 변환하기🦾
2023.01.14 - [BTY/TypeScript] - JsToTs : 비동기 처리 - Promise
유저 정보를 조회하는 비동기 요청을 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로 잘 추론됨도 확인 가능!
'source-code > TypeScript' 카테고리의 다른 글
"'React'은(는) UMD 전역을 참조하지만 현재 파일은 모듈입니다" 에러 해결 (2) | 2023.11.18 |
---|---|
getElementsByClassName에 for each 사용해 HTMLElement 접근하기 (0) | 2023.11.16 |
react-hook-form TS와 똑똑하게 사용하기 (0) | 2023.08.21 |
index signature 관련 타입 에러 (0) | 2023.08.21 |
JsToTs : 비동기 처리 - Promise (0) | 2023.08.21 |