ちょうど、こないだ書いたOpenAPI genarator の typescript-fetch について、他所で言及されていたのですが、その内容が軽く引っかかったので書いておきます。
レスポンスデータのプロパティがオプショナル(?)になる?
レスポンスデータのプロパティ全部に ? がついている(オプショナルな)ため、とても扱いづらい。API的には絶対あるはずの項目なのに、いちいちチェックを入れなければならない
? を外すの、一番最悪の場合は生成されたコードをさらに加工するという頭の悪い手段はありますが、それは本当の最終手段としたい。
すくなくとも私の手元ではそんなことにはならないので、ひょっとして type:object
の時、required
を指定してないんじゃないのかな? と思うのですが、どうなんでしょうか。
オプショナルなプロパティ
Specで下記のようなオブジェクトが定義されていた場合、オブジェクトのプロパティはすべてオプショナルになります。
components:
schemas:
ApiResponse:
type: object
description: APIレスポンス
properties:
code:
type: integer
description: レスポンスコード
minimum: 0
type:
type: string
description: レスポンスタイプ
message:
type: string
description: メッセージ
↓ Codegen して出力されてくるtypescriptの定義。
/**
*
* @export
* @interface ApiResponse
*/
export interface ApiResponse {
/**
*
* @type {number}
* @memberof ApiResponse
*/
code?: number;
/**
*
* @type {string}
* @memberof ApiResponse
*/
type?: string;
/**
*
* @type {string}
* @memberof ApiResponse
*/
message?: string;
}
code
type
message
すべてのプロパティがオプショナルになっており、ひょっとして元記事ではこの事を言っているのかなと思ったのですが、だとすると、これはSpec的に正しい解釈です。
オプショナルではないプロパティは、required
に記述されている必要があります。
下記のSpecから Codegen されたTSでは、プロパティはオプショナルにはなりません。
components:
schemas:
ApiResponse:
type: object
description: APIレスポンス
properties:
code:
type: integer
description: レスポンスコード
minimum: 0
type:
type: string
description: レスポンスタイプ
message:
type: string
description: メッセージ
required:
- code
- type
- message
/**
* APIレスポンス
* @export
* @interface ApiResponse
*/
export interface ApiResponse {
/**
* レスポンスコード
* @type {number}
* @memberof ApiResponse
*/
code: number;
/**
* レスポンスタイプ
* @type {string}
* @memberof ApiResponse
*/
type: string;
/**
* メッセージ
* @type {string}
* @memberof ApiResponse
*/
message: string;
}
nullable なプロパティ
一方で、nullable:true
なプロパティがTypescript側に反映されないようだ、という現象は確認していますが、どうやらnullableについては根深い問題のようで、プロパティ値に null
を入れるぐらいなら、プロパティごと null にしておいた方が無難であるようです。
typescript-fetch について
元記事では、他に2点の不満が挙げられており、typescript-fetch の出来が悪いというご意見のようです。
あまりにも OpenAPI generator のクォリティに難がありすぎるため、時間があれば pure js で書かれた、別のコード生成を試したかったところです。もしくはもういっそ自作した方が確実なのでは?とすら思っています。
別にtypescript-fetch に対して思い入れも義理もないですが、酷い言われようだなと思ったので、ついでに残り2点も擁護しておきます。
クラスやメソッドが探しにくい?
API種別ごとにクラスがあって、細かいエンドポイントごとに、メソッドが生えるため、目的のクラスとメソッドを探し出すのが面倒くさい
そんなに探しにくいですかね?
むしろそのための Swagger UI による自動ドキュメント生成だと思っているのですが。
こないだ書いた通り、typescript-fetch で出力されてくるフォーマットは タグ名がAPIクラス名となり、オペレーションID名がメソッド名となります。
↓のようなSpecであれば、Typescript側のコードでは AccountApi.postAccountAuth()
がメソッドとなります。
/account/auth:
post:
tags:
- account
summary: ログイン
operationId: postAccountAuth
responses:
'200':
description: successful
'400':
description: bad request
'404':
description: not found
クラス、メソッドを探すのが辛いということは、オペレーションIDを定義するための規約に問題があるんじゃないのかなあと思うのですが、どうなんでしょうね。
個人的には、下記のOpenAPI設計規約がとても勉強・参考になりました。
もし、 Swagger UI の出力の中に オペレーションID名 が表示されないのが不便である、という意味なら、表示するための設定があるそうです。
axiosより使いにくい?
挙動が typescript-axios と全く別もの
そりゃまあ別物なんでしょう、という話なんですが。
「挙動」というのが、Codegenの挙動なのか、吐き出されたTSの挙動なのか分かりませんが、ここではTSの話だと仮定して、そんなに差がありますかね?
accountApi.postAccountAuth().then((res) => {
// Success
}).catch((error) => {
// Error
})
返ってくるのが Promise なんで、レスポンスを受ける分には、特に差異を感じたことがないんですけど、もっと別の段階の話かもしれませんね。
私も使用歴は浅いので、使い込んでいくと色々と不満は出てくるのだろうと思います。