Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
HonoのRPCで真の型安全が欲しかった
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
kosei28
May 18, 2024
Programming
1.6k
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
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
300
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
830
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
470
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
300
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
570
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
1
2.1k
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
120
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.2k
Webの地図
yosuke_furukawa
PRO
6
5k
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.3k
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
iOSDCのペンライトを自動制御したい!
akkeylab
0
340
Featured
See All Featured
Fireside Chat
paigeccino
43
4k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
66k
Navigating Weather and Climate Data
rabernat
0
540
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.7k
Accessibility Awareness
sabderemane
1
230
Google's AI Overviews - The New Search
badams
0
1.6k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
700
Exploring anti-patterns in Rails
aemeredith
4
520
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
560
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
3
4.3k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
960
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はデータと全く異なる型をアサーションできてしまう ◦ 気づかぬうちに大事故が起こるかも …