Upgrade to Pro — share decks privately, control downloads, hide ads and more …

型安全RESTで爆速プロトタイピング – Hono RPC実践

型安全RESTで爆速プロトタイピング – Hono RPC実践

Avatar for tacke

tacke

May 27, 2025
Tweet

More Decks by tacke

Other Decks in Programming

Transcript

  1. Who am I? • AI Product Team Manager in MDM

    (LayerXから出向) • 社内向け内製 LLM Webアプリ を full TypeScript で開発 • モットー: “Build → Ship → Feedback” を最速ループ • 今⽇のテーマ: そのループを⽀える Hono RPC 2 武市 融紀 (X: @tacke_jp)
  2. The “API-Typing” Problem • フロント ↔ サーバー間は ただの JSON •

    🛑 型がない → 仕様 drift / runtime error • 既存解 ◦ gRPC ▶ readable じゃない ◦ tRPC ▶ JSON が独特 ◦ GraphQL / JSON-RPC ▶ 汎⽤だけど over-spec • 欲しいのは: ⼈間が読める REST + TypeScript 型安全 3
  3. Landscape Quick Scan 4 ⽅式 プロトコル∕ペイロード 読みやすさ コード⽣成 gRPC HTTP/2,

    ProtoBuf 😵 必要 GraphQL POST 1本 😐 (スキーマ必要) tRPC JSON-RPC 😐 不要 Hono RPC 純REST 😀 不要
  4. Enter Hono RPC • Hono: 超軽量Webアプリケーションフレームワーク (24k stars) • RPC

    機能 ◦ export type AppType = typeof app → hc<AppType>() だけ ◦ コード⽣成ゼロで型を共有 5 RESTful JSON に 型 をのせる コード⽣成 0, Hot-reload 100%を実現
  5. How it Works // server.ts const route = app .post(

    '/posts', zValidator('json', z.object({ title: z.string(), body: z.string(), })), (c) => c.json({ ok: true, message: 'Created!', }, 201) ) export type AppType = typeof route 6 // client.ts import { hc } from 'hono/client' import type { AppType } from '../server' const client = hc< AppType>('/api') const res = await client.posts.$post({ json: { title: 'Hello', body: 'Hono RPC is cool', }, }) // data: { ok: boolean; message: string } const data = await res.json()
  6. ✨ What I Like • 普通の REST + 強い型 =

    学習コストほぼゼロ • 変更 → 即 red-squiggle (tRPC 同等体験) • ルート毎に HTTP ステータス × 型 を区別可 • 型安全だから UI <-> API 断絶を防⽌ 7
  7. ⚠ Caveats / Gotchas in Practice • full-TS プロジェクト限定 •

    ミドルウェア経由の Response型は 現状推論されない • 複雑な型は IDE 上で … 折り畳まれる ◦ Tips: 末端 hover ∕ c.json<Foo>() のように明⽰型を付ける • ルータは method chain で書かないと推論が途切れる ◦ 公式ドキュメントでも⾮RPC部分の例はchainしていないので Coding Agentが引っ張られがち 8
  8. ⚠ Caveats / Gotchas in Practice (2) // ❌ NG:

    各ハンドラを後から繋げる const app = new Hono() app.get('/hello', (c) => c.json({ msg: 'hi' })) app.post('/hello', (c) => c.json({ ok: true })) export type AppType = typeof app // ←推論されない! 9 // ✅ OK: chain してから変数に束ねる const route = new Hono() .get('/hello', (c) => c.json({ msg: 'hi' })) .post('/hello', (c) => c.json({ ok: true })) export type AppType = typeof route // works
  9. Case Study: “Copilot” for ファンド契約書 • pnpm workspaceで web (Next.js)

    と backend (Hono API server) を分離 ◦ api で export type AppType → web で hc<AppType>() • SWR + Hono Client = 型安全 Data Fetching • API で { success: true | false } union を返す ◦ UI 側で toast 必須チェック を静的解析 • cookieAuth middleware は new Hono<{ Variables: AuthUser }>() で推 論注⼊ 10
  10. まとめ • REST 可読性 × 型安全 × 開発速度 = Hono

    RPC • プロトタイピング勢‧Edge Deploy 勢に特におすすめ • 試したくなったら 👉 pnpm add hono @hono/zod-validator 11