TypeScript REST APIクライアント

TypeScript (WebpackもしくはNode.js) で利用できるREST APIクライアントライブラリを調査した。

### まとめ

* [axios](https://github.com/axios/axios)と[typed-rest-client](https://github.com/Microsoft/typed-rest-client)がユーザー数が多く、開発も安定している。
	* 2019年11月時点ではaxiosの方が人気があるが、typed-rest-clientはTypeScript本家のMicrosoftがメンテしているため、デファクトになっていく可能性あり。
* Web標準的には[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch)だが、現時点ではブラウザサポートが不完全であり、TypeScriptで型を利用する部分は自力で実装する必要がある。
	* ブラウザサポートについては[Polyfillライブラリ](https://github.com/github/fetch)を使う手もある。
* Open API（Swagger）形式の仕様書がある場合は[OpenAPI Generator](https://openapi-generator.tech/)でクライアントSDKを生成すると効率がよい。
	* OpenAPI Generatorは[Swagger Codegen](https://swagger.io/tools/swagger-codegen/)をフォークしてコミュニティ主体で開発をしているもの。Swagger Codegenよりも開発が活発でGeneratorの種類も多い。（参考：[Swagger Codegen Fork: Q&A](https://openapi-generator.tech/docs/fork-qna)）
	* TypeScript用Generatorには、[typescript-axios](https://openapi-generator.tech/docs/generators/typescript-axios)、[typescript-fetch](https://openapi-generator.tech/docs/generators/typescript-fetch)や、[typescript-anglar](https://openapi-generator.tech/docs/generators/typescript-angular)などのフレームワーク向けのものもある。（参考：[Generators List](https://openapi-generator.tech/docs/generators#client-generators)）

### ライブラリの利用例

#### OpenAPI Generator

##### クライアントSDK生成

CLIツールはNPMやDockerイメージなど多様な形式でインストールできる。（参考：[CLI Installation](https://openapi-generator.tech/docs/installation)）

フレームワークに依存しないGeneratorには、axiosとfetchを使うものがあったが、上述の理由から前者の[typescript-axios](https://openapi-generator.tech/docs/generators/typescript-axios)を選択した。以下のコマンドでプロジェクトのsrcディレクトリにクライアントSDKを出力する。

```shell
openapi-generator-cli generate -g typescript-axios -i ./openapi.yaml -o ./src/client-axios
```

##### SDKを利用したAPI呼び出し

OpenAPI仕様書に記載されるURLと実際の接続先が異なる場合は、コンストラクタのbasePathパラメータにベースURLを指定すればよい。


```typescript
import { DefaultApi } from '@/client-axios';

const baseUrl = 'https://jsonplaceholder.typicode.com';
new DefaultApi({ basePath: baseUrl }).getToDo(1).then((res) => {
  console.log(res.data);
})
```

なお、出力コードがプロジェクトのLint設定と合わない場合は、検証対象外に入れておく。

```bash
# .eslintignore
src/client-axios
```

また、出力コード中でNode.jsのurlモジュールが使われているため、Webpack環境で型定義を `webpack-env` に限定している場合は、Node.jsモジュールの型定義も参照できるようにする必要がある。（参考：[TypeScript設定リファレンス](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#types-typeroots-and-types)）

```javascript
// tsconfig.json
{
  "compilerOptions": {
    "types": ["webpack-env", "node"]
  }
}
```

#### axios

レスポンスボディの型をinterfaceとして定義して型パラメータに指定すればよい。

```typescript
interface Todo {
  userId: number,
  id: number,
  title: string,
  completed: boolean,
}
```

```typescript
import axios from 'axios';

const url = 'https://jsonplaceholder.typicode.com/todos/1';
axios.get<Todo>(url).then((res) => {
  console.log(res.data);
});
```

### 参考

* OpenAPIからクライアントを作成する方法
	* [OpenAPIとTypeScriptで作る！チーム開発に適したWebアプリケーションの作り方](https://blog.5thfloor.co.jp/2019/06/26/webapp-development-with-openapi-and-typescript/#openapi-generator-api-)
	* [OpenAPI GeneratorでRESTful APIの定義書から色々自動生成する](https://ky-yk-d.hatenablog.com/entry/2019/01/13/234108)
* [Vue.jsクックブック](https://jp.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html)
	*  Fetch APIにはまだ問題が残っているため、axiosを推奨している。