TypeScriptでAxiosのレスポンスインターセプターに型をつける方法!API通信の基本から徹底解説
生徒
「TypeScriptでウェブサイトにデータを表示するとき、通信の処理を一つにまとめたいです。インターセプターというものがあると聞いたのですが、型をつけるのが難しくて悩んでいます。」
先生
「通信の前後で決まった処理を挟み込める機能ですね。TypeScriptでAxiosという道具を使うと、データの通信がとても安全になりますよ。」
生徒
「パソコンの操作もプログラミングも初めてなので、具体的な型付けのやり方や仕組みが知りたいです!」
先生
「それでは、基礎知識からエラーが起きたときの対策まで、分かりやすく順番に見ていきましょう!」
1. API通信とAxiosの基本を知ろう
インターネットでウェブサイトを見るとき、パソコンやスマートフォンは常に情報のやり取りを行っています。この情報のやり取りを専門用語でAPI通信と呼びます。API通信は、データを要求する側と、データを提供する側の二つの間で成り立っています。この通信を簡単に行うために開発された便利な道具が、Axiosと呼ばれる仕組みです。
Axiosを使うことで、複雑なインターネット通信の命令を、短いプログラムで記述できるようになります。パソコンを触ったことがない方でも、まずは「外部のデータを引っ張ってくるための魔法の道具」だと考えていただければ問題ありません。この道具をTypeScriptという安全なルールの中で使うことで、間違いのない確実な通信ができるようになります。
2. インターセプターとは何か
次に、今回の主役であるインターセプターについて解説します。インターセプターとは、英語で「待ち伏せして捕らえるもの」という意味があります。プログラミングにおけるインターセプターもまさにその通りで、データが届いた瞬間に、そのデータを待ち伏せして一足先に受け取る仕組みのことです。
例えば、手紙が届いたときに、本人が読む前に一度マネージャーが中身をチェックして、問題がなければ本人に渡すという場面を想像してください。このマネージャーの役割を果たすのが、レスポンスインターセプターです。すべての通信の返事に対して、共通の処理を一括で行うことができるため、プログラムの記述量を大幅に減らすことができる大変便利な機能です。
3. なぜ型をつける必要があるのか
TypeScriptを使う最大の理由は、プログラム内のデータに型という名札をつけることです。型をつけることで、そのデータが数字なのか、文字なのか、あるいは特定の情報が集まった塊なのかを明確に宣言できます。パソコンは非常に真面目なため、名札がないと中身が何であるかを判断できず、予期せぬエラーを起こしてしまうことがあります。
通信で返ってくるデータに型をつけておかないと、存在しない情報を読み込もうとして画面が真っ白になってしまう危険性があります。レスポンスインターセプターにしっかりと型を定義しておくことで、これから扱うデータがどのような形をしているかをパソコンに教えることができ、開発中のミスを未然に防ぐことができるようになります。
4. 最もシンプルなインターセプターの書き方
まずは、最も単純なインターセプターの仕組みをプログラムで書いてみましょう。ここでは、インターネットからデータが無事に届いたときに、そのままデータを次に引き渡すだけの処理を作成します。初めての方でも分かりやすいように、簡単な設定から順番に進めていきます。
import axios from 'axios';
axios.interceptors.response.use(
(response) => {
console.log("データが届きました");
return response;
},
(error) => {
console.log("問題が発生しました");
return Promise.reject(error);
}
);
上記のプログラムは、データが届いたとき、最初に画面の裏側で「データが届きました」という確認用の言葉を表示する設定です。このように、すべての通信で必ず実行したい共通の処理を一つの場所にまとめて記述することができます。
5. レスポンスデータに明確な型を定義する
それでは、届くデータに具体的な型をつけていきましょう。今回は、会員サイトを想定して、利用者の「名前」と「識別番号」が返ってくる通信を考えます。TypeScriptでは、データの設計図をインターフェースという機能を使って作成します。
interface UserInfo {
id: number;
name: string;
}
axios.interceptors.response.use(
(response) => {
const userData: UserInfo = response.data;
return response;
}
);
ここでは、識別番号を数字の型、名前を文字の型として定義しています。これにより、届いたデータの中に必ずその二つの情報が含まれていることを保証し、安全にプログラム内で使い回すことができるようになります。
6. 届いたデータの中身だけを抜き出す高度な型付け
通信の返事には、データそのもの以外にも、通信が成功したかどうかを表す番号や、通信にかかった時間など、様々な周辺情報が含まれています。しかし、実際に画面に表示したいのはデータの中身だけであることがほとんどです。そこで、インターセプターを使ってデータの中身だけを先に取り出す設定を行います。
import axios, { AxiosResponse } from 'axios';
interface CustomResponse<T> {
data: T;
}
axios.interceptors.response.use(
(response: AxiosResponse) => {
return response.data;
}
);
このプログラムでは、周辺情報をすべて削ぎ落とし、純粋なデータの中身だけを次の処理に引き渡すように改造しています。これを実現するためには、型を変化させる特殊な記述が必要になりますが、これによって以降のプログラムが非常にシンプルに書けるようになります。
7. 通信でエラーが起きたときの型安全な対策
インターネットの通信は、常に成功するとは限りません。電波が悪かったり、サーバーの電源が落ちていたりすると、通信は失敗します。この失敗のことをエラーと呼びます。安全なシステムを作るためには、失敗したときのことも考えて型をつけておく必要があります。
import axios, { AxiosError } from 'axios';
axios.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
if (error.response) {
console.log("サーバーからのエラー返答:", error.response.status);
} else {
console.log("通信そのものができませんでした");
}
return Promise.reject(error);
}
);
エラーの型として専門の設計図を指定することで、エラーが起きた原因がサーバーにあるのか、それとも自分のパソコンの設定にあるのかを、明確に見分けることができるようになります。これにより、画面に「通信に失敗しました」という親切な案内を確実に出すことができるようになります。
8. 実際の画面表示で型を活用する具体例
最後に、これまでに設定したインターセプターと型を使って、実際に利用者の情報を取得して画面に表示するまでの全体の流れを確認しましょう。型がしっかりと定義されているため、迷うことなく安全にデータを扱うことができます。
interface BookData {
title: string;
price: number;
}
async function fetchBookInfo() {
try {
const response = await axios.get<BookData>('/api/book');
console.log("本のタイトル:", response.data.title);
console.log("価格:", response.data.price);
} catch (error) {
console.log("データの取得に失敗しました");
}
}
このプログラムを実行すると、インターネットの向こう側から本の情報が届き、それぞれの内容が綺麗に仕分けされて画面の裏側に表示されます。型がついているおかげで、もしタイトルの文字を間違えて入力してしまっても、パソコンが即座に間違いを指摘してくれるため、安心してプログラムを書き進めることができます。