LaravelからTypeScriptの型が生成できるライブラリを作ってみた

Dec 21, 2022

はじめに

Laravel+TypeScript環境で役立つ便利なライブラリLaravel Typegenを作ってみたのでご紹介したいと思います。
npmパッケージとして配布していますがLaravel環境でのみ使えるものになります。

Laravel Typegenとは

Laravel TypegenはLaravelのコードからTypeScriptの型生成を行えるNode.jsライブラリです。

特徴としては以下があります。

  • LaravelのModelから型ファイル生成
  • Relation(hasManyやbelongsToなど)のサポート
  • Enumのサポート(PHP8.1のEnumやlaravel-enum)
  • Routingからziggy用の型ファイル生成

Warning

※動作はLaravel9からになります。

なぜ作ったのか

バックエンドをLaravelで、フロントエンド側をTypeScript(React/Vueなど)の構成で開発していると、Laravel側で書いたModel(マイグレーションファイル)やEnumファイルなどとTypeScriptの型定義で似たようなコードを重複して書くことがあると思います。

たとえばLaravelでpostsテーブル(Postモデル)を作成するときは以下のように書きます。

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->string('body');
        $table->timestamps();
    });
}

そして、TypeScriptではきっと以下のような型定義をするはずです。

type Post = {
    id: number;
    title: string;
    body: string;
    created_at?: string;
    updated_at?: string;
};

このように開発を進めていくと似たような記述をすることが多くなり、さらにテーブルでの変更があるとTypeScriptの型定義ファイル側も変更しなければならなかったりと効率が悪いです。

そこでLaravelのコードからTypeSCriptの型を生成して効率化できないかと考えこのライブラリを作成しました。

すでにいくつかLaravelからTypeScriptの型生成を行えるPHPのライブラリがありましたが、自分の欲しい機能がすべて揃ったもの(RelationやEnumなど)がなかったため自作しました。

使い方

  1. まずはインストールします
$ npm install -D @7nohe/laravel-typegen
  1. package.jsonにコマンドを追加します
{
    "scripts": {
        "typegen": "laravel-typegen"
    },
}
  1. コマンドを実行すると型が生成されます
$ npm run typegen

Modelの型はresources/ts/types/model.tsに生成されるので、それをimportしてきて使う形になります。

より詳しい使い方はREADMEをご確認ください。

仕組み

簡単に仕組みを説明したいと思います。
Laravel9からはArtisanコマンドの1つに model:show コマンドがあります。
以下のように実行するとModelのAttributeやRelation情報が出力されるというものです。

$ php artisan model:show User

このコマンドのオプションの1つに --json というものがありJSON値で先ほどの情報を出力できます。
これをNode.js側で読み込んでTypeScriptのCompiler APIで型生成をおこなっています。
こうするとPHP側でtsファイルを作成するよりも、より確実かつメンテナンスしやすい型生成処理が書けるため、PHPライブラリとしてではなく、Node.jsライブラリとして提供しています。

おわりに

理想はOpenAPIなどのスキーマを定義して、そこからTypeScriptコードを生成して開発するのが良いとは思いますが、中小規模のプロジェクトでモノリシックなアプリケーションの場合はそこまでやるのはなかなか難しいかと思います。 そんな時にこのLaravel Typegenを使えばLaravelとTypeScriptである程度のコードの共通化ができ、バグの減少に貢献できるかもしれません。

私もLaravel9とInertia.js(Vue3/TypeScript)環境での開発に活用しており、非常に役に立っております。