React 앱에서 서버와 통신할 때 fetchaxios를 자주 사용해.

TypeScript를 활용하면 API 응답 타입, 에러, 로딩 상태까지 정교하게 관리할 수 있어.


📘 예제 81: API 응답 타입 정의

type User = {
  id: number;
  name: string;
};

const getUser = async (): Promise<User> => {
  const res = await fetch('/api/user');
  if (!res.ok) throw new Error('서버 오류');
  const data: User = await res.json();
  return data;
};

✅ Promise<User>를 명시하면, 호출한 쪽에서 반환값 타입이 자동 추론돼.

fetch는 오류를 직접 처리해야 하므로 반드시 res.ok 체크 필요.


📘 예제 82: axios 요청/응답 제네릭

import axios from 'axios';

type Todo = {
  id: number;
  title: string;
  completed: boolean;
};

const getTodos = async () => {
  const res = await axios.get<Todo[]>('/api/todos');
  return res.data; // ✅ Todo[] 타입으로 추론됨
};

✅ axios.get<T>()처럼 제네릭으로 응답 타입을 지정하면, res.data가 자동으로 그 타입으로 인식돼.


📘 예제 83: 비동기 함수 타입 지정

const fetchPost = async (id: number): Promise<string> => {
  const res = await fetch(`/api/post/${id}`);
  const data = await res.json();
  return data.content as string;
};

✅ 비동기 함수의 리턴 타입은 Promise<T> 형식으로 명시.

명확한 반환 타입은 컴포넌트에서 사용할 때 큰 도움이 돼.


📘 예제 84: Error 타입 정의

type ApiError = {
  message: string;
  statusCode?: number;
};

const getData = async (): Promise<string> => {
  try {
    const res = await fetch('/api/data');
    if (!res.ok) throw new Error('요청 실패');
    const json = await res.json();
    return json.result;
  } catch (err) {
    const error: ApiError = {
      message: err instanceof Error ? err.message : '알 수 없는 오류',
    };
    console.error(error.message);
    throw error;
  }
};

✅ catch 블록에선 Error 타입을 명시적으로 판별해야 해.

err instanceof Error 패턴은 타입 안전한 방식으로 널리 쓰여.