そのAPIの型、定義されていますか?
フロントエンドで「型定義」といったらTypeScriptが思い浮かぶ人がほとんどではないでしょうか
宣言されている変数は型定義のおかげで意図しない値の代入を防げているでしょう
では、APIの返り値の型はどうですか? anyにしてませんか?
せっかく、TypeScriptを導入したにも関わらずanyを多用してしまっている...なんてことを防いでくれるライブラリ「aspida」を紹介します!
Aspidaが担ってくれること
パス・URL クエリ・ヘッダー・ボディ・レスポンス全てに型を指定可能
FormData / URLSearchParams の内容にも型を指定可能
HTTP クライアントは axios / fetch / node-fetch に対応READMEより
https://github.com/aspida/aspida/tree/main/packages/aspida/docs/ja#readme
実際にAspidaは以下のように型定義をしてくれます
import type { DefineMethods } from "aspida";
type User = {
id: number;
name: string;
};
export type Methods = DefineMethods<{
get: {
query?: {
limit: number;
};
resBody: User[];
};
post: {
reqBody: {
name: string;
};
resBody: User;
/**
* reqHeaders(?): ...
* reqFormat: ...
* status: ...
* resHeaders(?): ...
* polymorph: [...]
*/
};
}>;
さらにaspidaではパスとディレクトリ構造を一致させてくれます
例えば、APIのパスが https://example-api.com/users?limit={number} の形式の場合は
- myproject
- api
- users
- index.ts
のようにディレクトリを作ります
これが、パスが増えていくと
- myproject
- api
- users
- index.ts
- content
- index.ts
- action
- post
- index.ts
・・・
のように複雑なパスになっても可読性を保ったまま開発することができます!
ちなみに最初の例の場合のAPIを呼び出すコードは以下の通りです
// 公式サイトより
import aspida from "@aspida/axios";
import api from "../api/$api";
(async () => {
const userId = 0;
const limit = 10;
const client = api(aspida());
await client.v1.users.post({ body: { name: "taro" } });
const res = await client.v1.users.get({ query: { limit } });
console.log(res);
// req -> GET: /v1/users/?limit=10
// res -> { status: 200, body: [{ id: 0, name: "taro" }], headers: {...} }
const user = await client.v1.users._userId(userId).$get();
console.log(user);
// req -> GET: /v1/users/0
// res -> { id: 0, name: "taro" }
})();
このように型定義だけではなく、パスの面倒や毎回APIのURL/パスを書いて「どこかでタイプミスしてた...」なんてことからも救ってくれます
Aspidaの導入手順
npmからインストールできます
手順は公式リポジトリのReadMeで解説されているので割愛します
Aspidaで気を付けること
aspidaのビルドが必要
アプリケーションでaspidaを使うためにはaspidaのビルドが必要です
// package.json
{
"scripts": {
"api:build": "aspida"
}
}
$ npm run api:build
> api/$api.ts was built successfully.
Nuxtなどですでにnpmを使っている場合はpackage.jsonのscriptsの部分のdevなどにaspidaのコマンドを入れて
{
"scripts": {
"dev": "aspida && nuxt "
}
}
などにすると個々でコマンドを実行することができます!
aspidaを実際のプロダクトで使ってよかったこと
- 引数を入れ忘れない
- アプリケーション側のコードの可読性が上がった
aspidaがあることで引数が足りなかったり型が違ったりしたときにエラーを吐いてくれるのでAPI側でのエラーが大幅に減りました
また、それぞれの場所でaxiosでAPIコールするよりもaspidaを使ったほうが読みやすいです(切実)
終わりに
これからも便利なライブラリや新しい技術を積極的に取り入れて楽にコーディングをしたいですね!