RESTfulAPIで受け取るJSONのTypeScript型定義を自動生成してみる

記事「RESTfulAPIで受け取るJSONの型定義を考えてみる」を書いて3年経過してしまいましたが、JSONのTypeScript型定義を自動生成するツールを書いてみました。3年前の内容をベースにし、PowerCMS Xのschemeエンドポイントからモデルの構造を取得して各カラムの型を判定し、ファイルに出力するものです。

全てのカラムを出力する場合

例えばgetエンドポイントで記事オブジェクトを取得する時、colsパラメータを指定しなければ全てのカラムが含まれた状態でレスポンスが返ってきます。よって、node index.js entryを実行すると(いずれはパッケージ化したい)以下のような型定義が得られます。

type Entry = {
  id: number;
  title: string;
  text: string;
  text_format: string;
  assets: Asset[];
  text_more: string;
  excerpt: string;
  keywords: string;
  categories: Category[];
  tags: Tag[];
  extra_path: string;
  basename: string;
  user_id: User;
  previous_owner: number;
  allow_comment: boolean;
  workspace_id: number;
  uuid: string;
  attachmentfiles: Attachmentfile[];
  og_image: Binary;
  page_view: number;
  double_check: number;
  related_event: Event;
} & StatusType & DateType & RevisionType & AuditType;

StatusTypeAuditTypeはPowerCMS Xでモデルを作成する際のオプション「ステータス対応・有効期限対応」「自動監査」を反映したものです。オプションを選択することで決まったカラムがモデルに追加されるため、独自の定義にまとめました。StatusTypeは取り得る値も決まっているので、下記のような定義になっています。

export type StatusType = {
  status: 0 | 1 | 2 | 3 | 4 | 5;
}

編集タイプが「リレーション」、つまり他のモデルのオブジェクトを選択するカラムの型はCategory[]のように定義しています。よって、記事モデルの型定義と同時にカテゴリモデルの型定義も生成した方が良いか?と検討しているところです。

colsパラメータを指定した時

colsパラメータを指定してgetエンドポイントにアクセスすると、レスポンスには選択したカラムのみ含まれるようになります。よって、node index.js entry --cols id,title,text,assets,related_eventを実行すると以下のような型定義が得られます。

type Entry = {
  id: number;
  title: string;
  text: string;
  assets: AssetSummary[];
  related_event: EventSummary;
};

type AssetSummary = {
  id: number;
  label: string;
  file: Binary;
  workspace_id: number;
};

type EventSummary = {
  id: number;
  name: string;
  workspace_id: number;
};

colsパラメータを指定した場合はリレーション(単一選択・複数選択とも)の出力内容も限定的になるので、AssetSummaryのような定義を同時に出力しています。

課題

カラムの設定ではNullを許容しているけれど、CMSで入力を行えばnullになることはないカラムの型をどうするか?と考えています。(string | nullのような定義が多発するのもどうかなと。)また、アセットのURLを格納したPermalink等、カラムが存在しないがレスポンスには含まれるフィールドの出力も検討中です。

ツールの公開

GitHubの「hideki-a/powercmsx-typescript」にて暫定公開しています。