使用環境
OS: windows11
エディタ: Cursor(VSCodeでもOK?)
フレームワーク: Next.js
結論
- VSCode拡張機能のts-type-expandを使い、型の情報をテキストで取得
- 取得した情報をAIにぶん投げる
背景(読み飛ばしてOK)
コードの状況
tRPCを使う多人数開発のプロジェクトで、スキーマを定義しないままrouterを通していたファイルがあった。
既にfetchHoge.tsは完成されており、筆者がuseHoge.tsを作る、という状況。
./
├ _api/
│ ├ fetchHoge.ts/
│ ├ useHoge.ts/ # new!
│ └ router.ts/
├ _components/
│ └ ...some files
├ types.ts
import { fetchHogeHandler } from "./fetchHoge";
import { useHogeHandler } from "./useHoge";
import { createTRPCRouter, protectedProcedure } from "...";
import { z } from "zod";
export const HogeRouter = createTRPCRouter({
fetchHoge: protectedProcedure
.input(
z.object({
...
}),
)
.mutation(async ({ ctx, input }) => {
return fetchHoge({
...
});
}),
useHoge: protectedProcedure
.input(
z.object({
Hoge: // ここにスキーマがほしい
}),
)
.mutation(async ({ ctx, input }) => {
return useHogeHandler({
Hoge: input.hoge
});
}),
});
fetchHogeプロシージャにはoutputの型は示されていないが、tRPCで提供されている型推察のRouterOutputを使うことにより、クライアント側では型安全な処理が出来ている。
tRPCの型推察について
しかし、スキーマは存在しないので、useHogeプロシージャのinput用にどうにか型情報からスキーマを作成したい…
試したこと
手入力で作ろうとした
おそらく一番無難な解決方法。
…が、Hogeにあるプロパティ数が多すぎてVSCode上でカーソルを当てたときに省略されてしまう。
そもそもプロパティの多い型を可視化できないか?と思って調べたところ、ts-type-expandを見つける。
VSCodeのホバー情報で省略されてしまうTypeScriptの型情報をたっぷり表示させたい
tsconfig.jsonをいじる手もあるみたいだが、これは.gitignoreに乗っていないためローカルのみの変更ができず、断念。
スキーマの作り方(本編)
-
ts-type-expandをインストールし起動
-
スキーマを作りたい型を準備
hogeType.tstype hoge = { enumProperty: "option1" | "option2" | "option3"; arbitralProperty?: string; nullableProperty: number | null; arrayProperty: string[]; objectProperty?: { nestedProperty: boolean; }; unionProperty: number | string; intersectionProperty: number & string; };
-
hogeをクリックしてts-type-expand上に表示
-
型情報の全体をCopyボタンでテキスト出力
出力した型type hoge = { 'enumProperty': "option1" | "option2" | "option3", 'arbitralProperty': undefined | string, 'nullableProperty': null | number, 'arrayProperty': Array<string>, 'objectProperty': undefined | { 'nestedProperty': false | true }, 'unionProperty': string | number, 'intersectionProperty': never }
-
AIに以下の文とともに投げる
プロンプト to gpt-4o-miniこのテキストで示した型と同じ構造のものをzodオブジェクトとして出力してください。 undefinedやnullとのUnion型は.optional()や.nullable()を使用、 literal型のUnion型として表現されているものは、enum型に変更することで可読性を高めてください。 type hoge = ...
import { z } from 'zod';
const HogeEnum = z.enum(["option1", "option2", "option3"]);
const HogeSchema = z.object({
enumProperty: HogeEnum,
arbitralProperty: z.string().optional(),
nullableProperty: z.number().nullable(),
arrayProperty: z.array(z.string()),
objectProperty: z.object({
nestedProperty: z.boolean()
}).optional(),
unionProperty: z.union([z.string(), z.number()]),
intersectionProperty: z.never()
});
これで手書きせずにスキーマを書き起こすことができた。
筆者はCursorを使っているのでCursorChat内のgpt-4o-miniを使ったが、おそらくただのチャットボットを叩いても同じ結果が返ってくるはず。
仮に違う結果でも、手書きの工数は大幅に削減できそう。