0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【TypeScript / tRPC】既に存在する型から楽にスキーマを作成したい

Last updated at Posted at 2025-04-21

使用環境

OS: windows11
エディタ: Cursor(VSCodeでもOK?)
フレームワーク: Next.js

結論

  1. VSCode拡張機能のts-type-expandを使い、型の情報をテキストで取得
  2. 取得した情報をAIにぶん投げる

背景(読み飛ばしてOK)

コードの状況

tRPCを使う多人数開発のプロジェクトで、スキーマを定義しないままrouterを通していたファイルがあった。
既にfetchHoge.tsは完成されており、筆者がuseHoge.tsを作る、という状況。

src/features/hoge/
./
├ _api/
│    ├ fetchHoge.ts/
│    ├ useHoge.ts/ # new!
│    └ router.ts/
├ _components/
│    └ ...some files
├ types.ts
router.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上でカーソルを当てたときに省略されてしまう。
image.png
そもそもプロパティの多い型を可視化できないか?と思って調べたところ、ts-type-expandを見つける。
VSCodeのホバー情報で省略されてしまうTypeScriptの型情報をたっぷり表示させたい
tsconfig.jsonをいじる手もあるみたいだが、これは.gitignoreに乗っていないためローカルのみの変更ができず、断念。

スキーマの作り方(本編)

  1. ts-type-expandをインストールし起動

  2. スキーマを作りたい型を準備

    hogeType.ts
    type hoge = {
      enumProperty: "option1" | "option2" | "option3";
      arbitralProperty?: string;
      nullableProperty: number | null;
      arrayProperty: string[];
      objectProperty?: {
        nestedProperty: boolean;
      };
      unionProperty: number | string;
      intersectionProperty: number & string;
    };
    
  3. hogeをクリックしてts-type-expand上に表示

  4. 型情報の全体をCopyボタンでテキスト出力

    image.png

    出力した型
    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 }
    
  5. AIに以下の文とともに投げる

    プロンプト to gpt-4o-mini
    このテキストで示した型と同じ構造のものをzodオブジェクトとして出力してください。
    undefinedやnullとのUnion型は.optional()や.nullable()を使用、
    literal型のUnion型として表現されているものは、enum型に変更することで可読性を高めてください。
    type hoge = ...
    
result.ts
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を使ったが、おそらくただのチャットボットを叩いても同じ結果が返ってくるはず。
仮に違う結果でも、手書きの工数は大幅に削減できそう。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?