Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
HonoのRPCで真の型安全が欲しかった
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
kosei28
May 18, 2024
Programming
1.5k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HonoのRPCで真の型安全が欲しかった
kosei28
May 18, 2024
Other Decks in Programming
See All in Programming
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
250
今さら聞けない .NET CLI
htkym
0
200
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
7
2k
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
230
源内ハンズオン概要編
hideg
0
200
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
840
React本体のコードリーディング
high_g_engineer
1
150
引き算の組織 ― アウトカムとAIに全振りするために辞めたこと ― / Organization by Subtraction
hirokiyamamoto14
PRO
0
270
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
6.6k
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
0
1.9k
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
340
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
160
Featured
See All Featured
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
480
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
170
AI: The stuff that nobody shows you
jnunemaker
PRO
9
930
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.5k
Designing for Performance
lara
611
70k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
410
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.1k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
270
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
790
Thoughts on Productivity
jonyablonski
76
5.3k
Transcript
HonoのRPCで 真の型安全が欲しかった kosei28
kosei28 • 個人開発でWebやってます • TypeScript大好き ◦ フロントエンドもバックエンドも! • (一応)Honoのコントリビューター 𝕏:
@kosei_28
Honoとは • JS/TSのWebフレームワーク • 高速、軽量 • あらゆるJavaScriptランタイムで動作する ◦ エッジ環境でよく使われる •
RPCモード ◦ サーバーの型をクライアントと共有して型安全に API呼び出しができる機能
RPCモードを使ってみる import { Hono } from "hono"; import { z
} from "zod"; import { zValidator } from "@hono/zod-validator" ; const app = new Hono(); const routes = app.get( "/greeting" , zValidator ("query", z.object({ name: z.string() })), (c) => { const { name } = c.req.valid("query"); return c.json({ message: `Hello, ${name}!` }); } ); export type AppType = typeof routes; export default app; import { hc } from "hono/client" ; import type { AppType } from "./server" ; const client = hc<AppType>("/"); const res = await client.greeting.$get({ query: { name: "kosei28" }, }); const data = await res.json(); // { message: string; } console.log(data.message); // “Hello, kosei28!” server.ts client.ts
実は完璧な型安全ではない😭
Middlewareで返したResponseには型がつかない const error = true; app.use(async (c, next) => {
if (error) { return c.json({ error: "Internal Server Error" }, 500); } await next(); }); server.ts client.ts const res = await client.greeting.$get({ query: { name: "kosei28" }, }); const data = await res.json(); // { message: string; } console.log(data.message); // undefined console.log(data.error); // “Internal Server Error”
• Middlewareで極力Responseを返さない ◦ Middlewareの代わりに関数を用意して各ルートから呼び出す ◦ Middlewareの恩恵をあまり受けられない • ValidatorもMiddleware ◦ Zod
Validatorのバリデーションエラーによる Responseはどうにもできない ◦ そもそもバリデーションエラーを発生させない ▪ Validatorでのバリデーションは型チェックだけにする ▪ リクエスト前にクライアントでもバリデーションする • スキーマを別のモジュールに定義して、サーバー・クライアントで共有する 対策1: Middlewareで返すResponseをどうにかする
対策2: 各ルートのResponseは全て200番台で返す • Response.okでResponseがMiddlewareによるものか判別できる ◦ Middlewareでは200番台のResponseを返さない • デメリット ◦ 不適切なステータスコード?
▪ GraphQLは全て200 ▪ 割り切ってしまえるなら問題なし ◦ 結局、MiddlewareのResponseの型はわからない ◦ ステータスコードによる型の分岐が使えない
const routes = app.get( "/greeting" , zValidator ("query", z.object({ name:
z.string() })), (c) => { const { name } = c.req.valid("query"); if (error) { return c.json({ success: false as const, error: "Internal Server Error" , }); } return c.json({ success: true as const, data: { message: `Hello, ${name}!` }, }); } ); res.okの場合は型安全 const res = await client.greeting .$get({ query: { name: "kosei28" }, }); if (res.ok) { // この中では型安全 const result = await res.json(); if (result.success) { console.log(result.data.message); } else { console.log(result.error); } } server.ts client.ts
まとめ • HonoのRPCモードはとても便利だが真の型安全ではない • 対策 ◦ MiddlewareによるResponseを減らす ◦ クライアントでもバリデーションすることが重要 ◦
各ルートのResponseを200番台で返せば部分的な型安全にできる • 型があるからと言って安全ではない ◦ TypeScriptはデータと全く異なる型をアサーションできてしまう ◦ 気づかぬうちに大事故が起こるかも …