下の動画を見て、やはりデータベース ⇔ バックエンド ⇔ フロントエンドの間でスキーマ定義が半自動的に同期される仕組みがあるというのは便利だな〜と思ったので、そのために使えそうなライブラリを調べました。
===
===
目標は、データベースを変更 → TypeScriptの型定義が半自動で更新される → バックエンドとフロントエンドの両方のプロジェクトで型定義が共有される、という状態にすることです。
バックエンドのDBアクセス、REST APIから、フロントエンドのReactコンポーネントのPropsまで、アプリケーション全体で共通の型定義を使いたい |
1. schemats
動画で使われているのは、schemats というライブラリでした。これは、データベースからテーブルのスキーマを読み取って、TypeScriptの型定義を生成してくれるというもののようです。
サンプルコードやこちらのブログ記事を見ても分かるとおり、このライブラリは特にORMのようなものを介さずに自分で直接SQLクエリーを書いてデータベースにアクセスしたいという場合に向いているようです。
3. Prisma
専用のスキーマ定義ファイルからTypeScriptの型定義を生成します。
このPrismaスキーマをデータベースから自動生成するワークフローと、まず自分でPrismaスキーマを書いて、それをマイグレーションでデータベースに反映するワークフローの2種類をサポートしているそうです。
DBからPrismaスキーマを生成 |
PrismaスキーマからDBに反映 |
ただ、こちらのNext.jsでのサンプルを見た感じでは、データベース⇔バックエンドの間では型定義の同期が取れていますがフロントエンド側まではそれが共有されていません。例えば個々のReactコンポーネントのPropsについてはそれぞれに型定義をおこなっているようです。フロントエンド側にまで型定義を共有出来る方法があるのかどうかについてはよく分かりませんでした。
TypeScriptを使う場合のORMライブラリとしてかなり人気があると思われるTypeORMですが、別途 typeorm-model-generator というCLIツールを組み合わせるとデータベースからTypeORM用のモデルクラスを生成することが出来るようです。
Node.js用のORMとしておそらく最も使われているSequelizeですが、これ向けにも sequelize-typescript-generator というCLIツールが見つかりました。Sequelize を採用することが決まっている場合は、こちらの組み合わせも良いかも知れません。 ただ、Sequlize向けに生成されたモデルクラスをそのままフロントエンド側で参照してReactコンポーネントなどで使えるかというと、それは厳しいのではないかと思います。
考察
「DBから生成した型定義をバックエンドからフロントエンドまで共通で使いたい」と書きましたが、結局よく考えてみると、
①バックエンド側でDBアクセスをするための型(テーブル単位)②APIのインターフェースとしての型(ユースケース単位)③フロントエンドのコンポーネント間でやり取りするための型(UI部品単位)
はそれぞれに用途が異なるので完全に同じものを使い回すというようなことは現実的ではなさそうです。
ただ、①②③の中でもカラム単位で見れば共通の定義を抽出して参照することは可能ではないかと思います。
例えば冒頭の動画で紹介されているように「通知メールの許可設定」を表すカラムについて、当初 Boolean だったものが後から Number に変更されたというようなケースでは、カラム単位で共通の型定義を参照していれば、一箇所が(コマンド一つで半自動的に)変更されれば(バックエンド、フロントエンド含めて)それを参照している全ての箇所がコンパイル時にエラーとなって容易に修正出来るようになるというイメージです。
このような用途で考えると、今回調べたライブラリの中では schemats は一度試してみる価値があるかも知れないと思いました。
🍻