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
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
関数型プログラミングのメリットって何だろう?
wanko_it
0
180
SREの積み重ねがAI駆動開発のガードレールになった ― 7つの実践/SRE Guardrails The 7
tomoyakitaura
8
4.8k
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
150
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
2.7k
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
270
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
330
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
6.5k
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
370
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
260
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
530
吝嗇家のためのAI活用 / AI development for miser - ChatGPT + Issue Driven Development
tooppoo
0
190
Featured
See All Featured
Leo the Paperboy
mayatellez
8
1.9k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
220
Bash Introduction
62gerente
615
220k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
220
Context Engineering - Making Every Token Count
addyosmani
9
1k
Google's AI Overviews - The New Search
badams
0
1.1k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.2k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
220
The browser strikes back
jonoalderson
0
1.4k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
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はデータと全く異なる型をアサーションできてしまう ◦ 気づかぬうちに大事故が起こるかも …