openapi-typescript
openapi-typescript
はOpenAPI SpecからTypescriptの型を生成してくれるライブラリです.
例えば下のようなOpenAPI Specから
openapi: "3.0.3"
info:
title: "Sample"
version: "1.0.0"
paths:
"/todo":
get:
summary: "get todo"
responses:
"200":
description: "success"
content:
application/json:
schema:
$ref: "#/components/schemas/Todo"
components:
schemas:
Todo:
type: object
required: ["commonProp"]
properties:
commonProp:
type: string
このような型が生成できます.
export interface components {
schemas: {
Todo: {
commonProp: string;
};
};
};
readOnly属性(OpenAPI Spec)
OpenAPIではスキーマのプロパティに対してreadOnly属性(writeOnly)を付与することができる.これにより一つのスキーマでリクエストとレスポンスで異なるスキーマを表現できる.
例えば次のようなOpenAPI Specの場合
openapi: "3.0.3"
info:
title: "Sample"
version: "1.0.0"
paths:
"/todo":
post:
summary: "post todo"
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Todo"
responses:
"200":
description: "success"
content:
application/json:
schema:
$ref: "#/components/schemas/Todo"
components:
schemas:
Todo:
type: object
required: ["commonProp", "readProp"]
properties:
commonProp:
type: string
readProp:
type: string
readOnly: true
Postのリクエストとレスポンスに同じTodo
スキーマを使用しているが、生成されるドキュメントでは
- リクエスト =>
{"commonProp": "string"}
- レスポンス =>
{"commonProp": "string","readProp": "string"}
といった型として表現される。
openapi-typescript@v6 の場合
先ほどのreadProp
を含むOprnAPI Specから現行のopenapi-typescript(6.7.1)による型生成を行うと以下のような出力が得られる.
export interface components {
schemas: {
Todo: {
commonProp: string;
readProp: string;
};
};
};
OpenAPI Spec上のreadOnly
が無視された型が生成される.
もしリクエスト用の型を作りたい場合は,
type Todo = components["schemas"]["Todo"];
type TodoRequest = Omit<Todo, "readProp">;
/*
type TodoRequest = {
commonProp: string;
}
*/
のように手動で取り除く必要があった.
- Issueは上がっているが進展は無さそう (対応するための実装は書いてある)
openapi-typescript@v7 の場合
同様に先ほどのOpenAPI Specを openapi-typescriptの7.0.0-next.5
で型生成を行うと次のような型が生成される.
export interface components {
schemas: {
Todo: {
commonProp: string;
readonly readProp: string;
};
};
};
このようにOpenAPI Spec上でreadOnly
属性を付けたプロパティにはTypescript上でもreadonly
修飾子が設定されている.
これで先ほどのTodoRequestを作成したい場合はreadonly
を取り除くようなTypeを書いて
type Todo = components["schemas"]["Todo"];
type readonlyプロパティ除外する型<T> = ...
type TodoRequest = readonlyプロパティ除外する型<Todo>
のようにすれば良い.
まとめ
readonly
がついて嬉しい!(ただし, writeOnly
は非対応)
openapi-typescript@v7ではRedoclyによるスキーマ検証や,EnumをトップレベルにUnion型として生成する等の機能が含まれています.
(参考) readonlyプロパティ除外する型
任意のobject型からreadonly修飾子のついたプロパティを除外する方法は次のような方法がある.
こちらについてはまた別の機会に記事にするかもしれません.