Prisma Client Extensionsを試す(Computed Fields)
Prisma Client Extensions
PrismaのClient ExtensionsがPreview機能として使えて、PrismaClientを拡張することができるようになりました。
使い方は多様で、上記にExampleがたくさん乗っています。ということでComputed Fieldsを実際に試してみました。
Computed Fieldsの設定
Client Extensionsを使ってComputed Fields(仮想フィールドと言ったりもする)をPrismaのModelに追加することができます。「データベースの列としては存在しないんだけど、Modelに存在していると便利なフィールド(関数もいける)」が追加できるということです。
本家からの引用 ですが、以下のように定義します。
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient()
.$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`;
},
},
},
},
})
.$extends({
result: {
user: {
displayName: {
needs: { fullName: true, email: true },
compute(user) {
return `${user.fullName} <${user.email}>`;
},
},
},
},
});
firstName
と lastName
がデータベースの列データとして格納されているが、 fullName
だったり displayName
として、演算した結果を使えるようにする実装です。上記で面白いのは $extends
を2回使って、多段で演算している点です。
.$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`;
},
},
},
},
})
上記のように1回目は fullName
を firstName
と lastName
から演算しています。 needs
にも firstName
と lastName
があるのがわかります。
.$extends({
result: {
user: {
displayName: {
needs: { fullName: true, email: true },
compute(user) {
return `${user.fullName} <${user.email}>`;
},
},
},
},
});
そして、上記のように2回目で、1回目の fullName
を使いつつ、さらに email
を使って displayName
を追加しています。 needs
に1回目に定義した fullName
と、新たに email
が追加されているのが確認できます。
Computed Fieldsを使う
定義が終わったので実際に使ってみます。何がすごいかと言うと、ちゃんとComputed Fieldに対して型補完が効くのです!
上記キャプチャにあるように、 fullName
も displayName
も出てくるのが確認できます。ということで以下のコードを入力すると:
const users = await prisma.user.findMany({ take: 5 });
for (const user of users) {
console.info(`- ${user.displayName}`);
}
結果は↓のようになります。
- Kamille Berge <Mavis84@yahoo.com>
- Heaven Wisoky <Victoria_Kassulke@yahoo.com>
- Aaliyah Heaney <Gwendolyn61@gmail.com>
- Queenie Kozey <Brayan.Krajcik@gmail.com>
- Eldridge Padberg <Luther.Lowe@hotmail.com>
これはかなり便利に使えそうですね!
おまけ
せっかくなのでもうちょっといじってみます。PrismaのModelは、POJO(Plain Old JavaScript Object)なので、オブジェクトの中身を見ただけでは果たしてUser Modelだったのかどうか、ということが判断できません(instanceofが使えない)。基本的には問題にならないのですが、場合によっては厄介になることがあります(e.g. Modelの種類でロジックを分けたいときなど)。
ということで自前でModelの情報を入れちゃうという使い方もあるかなと思いました。
const prisma = new PrismaClient().$extends({
result: {
user: {
type: {
needs: {},
compute() {
return 'User' as const;
},
},
},
},
});
ちゃんと型補完も効きます。
switch文とかで使うときにもちゃんと User
が補完で出てきます。素敵!
実行すると以下のようにちゃんと User
として認識されるのがわかります。
const user = await prisma.user.findFirstOrThrow();
console.log(`The type is ${user.type}`);
結果
The type is User
ということでPrismaのModelの可能性がこれだけでも拡がるのがワクワクしますね。
Discussion