🤖
【TypeScript】fetchしたデータに型を付与する
node-fetch
などを使ってfetchしたデータはResponse
型で返ってくる。
このとき送られてきたデータにスキーマ情報が含まれていないため、型が不明となってしまう。
const response = await fetch(`${process.env.api}`, {
headers: {
Authorization: idToken
}
});
こういった場合、クライアント側で受け取ったデータに型情報を付与できるwrap関数を作成する。
ついでにエラーハンドリングも追加。
const fetchWithErrorHandling = <T>(
url: RequestInfo,
options: RequestInit
): Promise<T> =>
fetch(url, options)
// 1. ネットワーク周りなどのリクエスト以前の段階でのエラーを処理する
.catch((e) => {
throw Error(e);
})
// 2. サーバサイドで発行されたエラーステータスを処理する
.then(handleErrors)
// 3. 以上2つをパスした正常なレスポンスからJSONオブジェクトをパースする
.then((res) => res?.json());
const handleErrors = async (res: void | Response) => {
// NOTE: AbortError が発生した場合のみ。res === void に成りうる
if (!res) return;
if (res.ok) return res;
let body: ApiErrorResponse | undefined = undefined;
try {
body = await res.json();
} catch {
// Non json response
}
switch (res.status) {
case 400:
throw new ApiRequestError('INVALID_TOKEN', body);
case 401:
throw new ApiRequestError('UNAUTHORIZED', body);
case 403:
throw new ApiRequestError('FORBIDDEN', body);
case 500:
throw new ApiRequestError('INTERNAL_SERVER_ERROR', body);
case 502:
throw new ApiRequestError('BAD_GATEWAY', body);
case 404:
throw new ApiRequestError('NOT_FOUND', body);
default:
throw new ApiRequestError('UNHANDLED_ERROR', body);
}
};
こんな感じで使う
type MyDataType = {
id: number;
name: string;
}
const response = await fetchWithErrorHandling<MyDataType>(`${process.env.api}`, {
headers: {
Authorization: idToken
}
});
Discussion