🙌

OpenAIPスキーマからTypeScriptの型を生成するライブラリ比較

2023/08/09に公開

今回は以下のライブラリを比較してみます。

以下のスペックファイルを用意してコード生成してみます。

openapi: 3.0.0
info:
  title: API
  version: 0.1.0
servers:
  - url: http://localhost:8000
paths:
  /signin:
    post:
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                password:
                  type: string
              required:
                - "email"
                - "password"
      responses:
        '201':
          description: OK
        '401':
          description: UnAuthorized
          content:
            application/json:
              schema: 
                type: object
                properties:
                  code:
                    type: string
                  message: 
                    type: string
                required:
                  - "code"
                  - "message"

openapi-typescript

TypeScriptの型を生成してくれます。
また、生成した型を利用してfetchを呼べるライブラリもセットで用意されています。

生成されるコード

export interface paths {
  "/signin": {
    post: {
      requestBody?: {
        content: {
          "application/json": {
            email?: string;
            password?: string;
          };
        };
      };
      responses: {
        /** @description OK */
        201: never;
        /** @description UnAuthorized */
        401: {
          content: {
            "application/json": {
              code?: string;
              message?: string;
            };
          };
        };
      };
    };
  };
}

export type webhooks = Record<string, never>;

export type components = Record<string, never>;

export type external = Record<string, never>;

export type operations = Record<string, never>;

利用する側のコード

const { POST } = createClient<paths>({ baseUrl: 'https://example/v1/' })
const { data, error } = await POST('/signin', {
  body: {
    email: 'email',
    password: 'password'
  }
})

openapi-typescript-codegen

fetchクライアントを含むサービスクラスと、諸々を生成してくれます。
以下のディレクトリ構成でファイルが作成されます。

.
├── core
│   ├── ApiError.ts
│   ├── ApiRequestOptions.ts
│   ├── ApiResult.ts
│   ├── CancelablePromise.ts
│   ├── OpenAPI.ts
│   └── request.ts
├── index.ts
├── models
└── services
    └── DefaultService.ts

サービスクラスの中身は以下のようになっています。

import type { CancelablePromise } from '../core/CancelablePromise'
import { OpenAPI } from '../core/OpenAPI'
import { request as __request } from '../core/request'

export class DefaultService {
  /**
   * @param requestBody
   * @returns any OK
   * @throws ApiError
   */
  public static postSignin(requestBody?: {
    email: string
    password: string
  }): CancelablePromise<any> {
    return __request(OpenAPI, {
      method: 'POST',
      url: '/signin',
      body: requestBody,
      mediaType: 'application/json',
      errors: {
        401: `UnAuthorized`
      }
    })
  }
}

orval

リクエスト、レスポンスの型、axiosクライアント、Result型を生成してくれます。
また、オプションの設定によりReact queryのhooksやMock Service Workerのモックを
生成することができます。

import * as axios from 'axios'
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
export type PostSignin401 = {
  code: string
  message: string
}

export type PostSigninBody = {
  email: string
  password: string
}

export const postSignin = <TData = AxiosResponse<void>>(
  postSigninBody: PostSigninBody,
  options?: AxiosRequestConfig
): Promise<TData> => {
  return axios.default.post(`/signin`, postSigninBody, options)
}

export type PostSigninResult = AxiosResponse<void>

openapi-zod-client

zodのスキーマとZodiosクライアントを生成してくれます。

import { makeApi, Zodios, type ZodiosOptions } from '@zodios/core'
import { z } from 'zod'

const postSignin_Body = z
  .object({ email: z.string(), password: z.string() })
  .passthrough()

export const schemas = {
  postSignin_Body
}

const endpoints = makeApi([
  {
    method: 'post',
    path: '/signin',
    alias: 'postSignin',
    requestFormat: 'json',
    parameters: [
      {
        name: 'body',
        type: 'Body',
        schema: postSignin_Body
      }
    ],
    response: z.void(),
    errors: [
      {
        status: 401,
        description: `UnAuthorized`,
        schema: z
          .object({ code: z.string(), message: z.string() })
          .passthrough()
      }
    ]
  }
])

export const api = new Zodios(endpoints)

export function createApiClient(baseUrl: string, options?: ZodiosOptions) {
  return new Zodios(baseUrl, endpoints, options)
}

以下も試してみましたが、上手く動かせませんでした 😅

以上です👋

Discussion