일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 그리디
- 컴퓨터과학
- 프론트엔드개발자
- nodejs
- git
- computerscience
- 백준
- 야놀자
- CS
- 국비지원
- 호이스팅
- 국비지원취업
- js
- Javascript
- 부트캠프
- 너비우선탐색
- html/css/js
- 패스트캠퍼스
- 알고리즘
- 컴퓨터공학
- BFS
- CSS
- DFS
- cpu
- 자바스크립트
- KAKAO
- github
- LinkSnap
- 코딩테스트
- 코테
- Today
- Total
My Boundary As Much As I Experienced
AxiosInstance의 반환값은 AxiosResponse<T>라는데 왜 사용하면서 반환값으로 Promise<T>만 써왔을까? 본문
AxiosInstance의 반환값은 AxiosResponse<T>라는데 왜 사용하면서 반환값으로 Promise<T>만 써왔을까?
Bumang 2024. 6. 6. 18:00
궁금해진 계기
어제 백엔드 개발자 분이 주신 데이터를 보고 status, data 부분이 계속 반복된다는걸 깨닫고 ResponseType이란걸 만들어서 재사용하려고 했다.
type ResponseType<T> = {
status: T,
data: ...
}
그리고 여느때와 마찬가지로 API함수 안에서 AxiosInstance를 사용해서 호출한 값을 반환하려 했다.
그리고 Promise<ResponseType<T | false>>를 타입지정해주려 했는데
res에는 data라는 컬럼이 없다는 에러가 나왔다.
export const getAbuserData = async (id: string): Promise<ResponseType<AbuserDataResponse | false>> => {
if (!id) return false
const res = await API.get(`/abuser/${id}`);
return res.data.result;
};
API명세서에는 분명 있는데 왤까.. 그런데 ResponseType을 지우고
Promise<T | false>만 사용하니 제대로 호출이 되고 타입지정도 잘 되는걸 볼 수 있었다.
그러고보니 나는 지금까지 백엔드에서 주는 명세서에는 data와 status 필드가 다 있었는데
Promise<T>를 사용할 때 data에 있는 데이터만 T를 사용해서 지정했지
data, status 필드를 다 포함하는 wrapping type을 쓴 적은 없었다.
기본적으로 Axios로 호출 후 반환된 값들은 모두 AxiosResponse<T>로 맵핑되어있다.
그래서 찾아보니 Axios로 호출하여 반환한 값들은 모두 기본적으로 AxiosResponse<T>가 맵핑되어있다고 한다.
그러므로 내가 Promise<ResponseType<T | false>>로 지정했던게
사실 Promise<AxiosResponse<ResponseType<T | false>>>로 처리되고 있던 거였다.
export const getAbuserData = async (id: string): Promise<ResponseType<AbuserDataResponse | false>> => {
if (!id) return false
const res = await API.get(`/abuser/${id}`);
return res.data.result;
};
AxiosResponse<T>가 생략되어있다면 굳이 다 표기하는 것은 가능한가?(Promise<AxiosResponse<T>>)
나는 지금까지 작업하면서 AxiosResponse<T>가 기본적으로 맵핑되어 있는지 전혀 몰랐다.. 그렇다면 AxiosResponse를 생략하지 않고 다 표기하는 것은 가능한가?
결론은 가능하다. 그러나 이렇게 표기하면 AxiosInstance를 거치지 않은 반환값을 리턴할 때 AxiosResponse에 담은
(예를 들어 패러미터가 undefined이면 early return을 해야될 때)
'T는 AxiosResponse<T>에 포함되지 않는다'는 식의 에러를 경험할수도 있다.
export const getAbuserData = async (id: string): Promise<AxiosResponse<AbuserDataResponse | false>> => {
if (!id) return false // Type 'boolean' is not assignable to type 'AxiosResponse<false | AbuserDataResponse, any>'.ts(2322)
const res = await API.get(`/abuser/${id}`);
return res.data.result;
};
나는 일례로 id값이 혹여 없다면 false를 바로 내려주게 하려고 했다.
그런데 Promise<T | false>가 아니라 AxiosResponse<T | false>로 하니
이걸 아래 예시처럼 AxiosResponse<T>에 맞는 형태로 꼭 리턴해야되는 번거로움이 발생했다.
export const getAbuserData = async (id: string): Promise<AxiosResponse<AbuserDataResponse | false>> => {
if (!id) {
return {
data: false,
status: 400,
statusText: 'Bad Request',
headers: {},
config: {},
} as AxiosResponse<false>; // 필요한 최소한의 AxiosResponse 구조를 반환
}
const res = await API.get(`/abuser/${id}`);
return res.data.result;
};
그러므로 그냥 AxiosResponse를 명시해줘서 힘들게 코드량을 늘릴 필요는 없을거 같다!
Axios가 아니라 fetch API를 사용할 때는?
이럴 때는 status, data등을 다 표기한 wrapper type을 사용하는게 편리할수도 있다.
interface ResponseType<T> {
data: T;
status: number;
statusText: string;
}
const getData = async <T>(url: string): Promise<ResponseType<T>> => {
try {
const response = await fetch(url);
// 응답이 성공적인지 확인
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// JSON 형태로 변환
const data: T = await response.json();
// 상태 코드와 데이터를 함께 반환
return {
data,
status: response.status,
statusText: response.statusText
};
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
};
역시 여러모로 Axios를 사용해서 편했던 이유를 알게되었고 앞으로도 자주 이용하자는 생각이 드는 스터디였다.
'FrontEnd > TypeScript' 카테고리의 다른 글
타입스크립트로 constant 객체를 효과적으로 관리하는 방법 (0) | 2024.06.18 |
---|---|
타입에러 해결법) Property Chaining이 깊을 때 필요한 속성만 타입 단언 해주는 법 (0) | 2024.06.07 |
TIL: 타입스크립트 is란 무엇인가? / 객체 타입 단언 시 특정 속성만 단언해도 된다? (0) | 2024.05.19 |
as const와 enum 중에 무엇을 쓸까 (0) | 2024.05.09 |
unknown 타입은 왜 쓰나? (0) | 2024.05.04 |