クライアントとサーバー間の型推論
コード生成なしで完全に型付けされたクライアントを取得します。
「クライアントとサーバー間の型推論」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。
ルーター型の共有
クライアントは、サーバーのルーター型をインポートすることで型安全性を得ます。これは型のみのインポートです。サーバーの実行時コードがクライアントで実行されることはなく、静的なコントラクトだけが境界を越えます。
import type { AppRouter } from '../server/router';
// type-only import - erased at build time型付きクライアントの作成
createTRPCClient(またはプロキシ版)にAppRouterを型パラメーターとして指定します。するとクライアントオブジェクトがサーバールーターの形状をそのまま反映し、すべてのプロシージャで完全なオートコンプリートが利用できます。
import { createTRPCClient, httpBatchLink } from '@trpc/client';
const client = createTRPCClient<AppRouter>({
links: [httpBatchLink({ url: 'http://localhost:3000' })],
});プロシージャの呼び出し
呼び出しはルーターのツリー構造を反映します。ネストしたプロシージャuser.byIdにはclient.user.byIdでアクセスし、その上で.queryまたは.mutateを呼び出します。入力と出力はサーバーから型付けされます。
const user = await client.user.byId.query({ id: 1 });
// user is typed exactly as the server resolver returns推論された入力
クライアントは、サーバーのスキーマから各プロシージャの入力を認識します。形状が間違っている値を渡すと、アプリを実行する前にコンパイルエラーになります。
await client.user.byId.query({ id: 1 }); // ok
// await client.user.byId.query({ id: 'x' }); // error: id must be number
// await client.user.byId.query({}); // error: id is required推論された出力
戻り値の型もクライアントに伝わります。クエリの解決後の値は、サーバーのリゾルバーが返す値と正確に一致するため、その後続のコードも完全にチェックされます。
const u = await client.user.byId.query({ id: 1 });
const name: string = u.name; // ok if server returns name: stringクライアントでのミューテーション
ミューテーションは.mutateで呼び出します。入力にはスキーマに基づく型が適用され、出力はリゾルバーから推論されるという、同じ推論の仕組みが使われます。
const created = await client.user.create.mutate({ name: 'Bea' });
// created is typed from the create resolver's return推論の流れ
型がどのように伝わるかを追ってみましょう。サーバー上のzodスキーマから入力型が推論され、リゾルバーの戻り値から出力型が推論されます。typeof appRouterによって両方がAppRouterに取り込まれ、クライアントはその型を呼び出し可能なメソッドに対応付けます。1か所の変更が自動的に全体へ波及します。
// schema -> input type
// resolver -> output type
// appRouter -> AppRouter (both captured)
// client<AppRouter> -> typed callsヘルパー型の推論
tRPCには、Reactコンポーネントなどで再利用するために、入力型と出力型を取り出すヘルパーが用意されています。inferRouterInputsとinferRouterOutputsを使うと、AppRouterからそれらの型のマップを取得できます。
import type { inferRouterOutputs } from '@trpc/server';
type Outputs = inferRouterOutputs<AppRouter>;
type User = Outputs['user']['byId'];不整合が生じない保証
クライアントは実際のルーター型から型付けされるため、サーバーとクライアントに不整合が生じることはありません。プロシージャ名を変更したり入力を変更したりすると、呼び出しを更新するまでクライアントはコンパイルに失敗します。コンパイラーがコントラクトテストの役割を果たします。
// Server renames user.byId -> user.find
// client.user.byId becomes a type error immediatelyバッチ処理とリンク
links配列でトランスポートを設定します。httpBatchLinkは、同じティック内で行われた複数の呼び出しを1つのHTTPリクエストにまとめ、ラウンドトリップを減らします。これは実行時の最適化であり、型には影響しません。
links: [httpBatchLink({ url: '/trpc' })]
// Several .query calls in one tick -> one request実践でのエンドツーエンド
その結果、client.user.byId.query(...)をローカル関数のように呼び出せます。入力のオートコンプリート、引数のチェック、型付けされた結果を利用でき、すべてが生成ファイルなしでサーバーコードから導出されます。これが推論によって実現されるエンドツーエンドの型安全性です。
const u = await client.user.byId.query({ id: 7 });
console.log(u.name); // fully typed, no codegen確認テスト
クライアントとサーバー間の推論についての理解度を確認します。
まとめ
完全な型安全性を備えたtRPC APIを利用しました。
AppRouterを型のみのインポートとして読み込みます。createTRPCClient<AppRouter>はルーターのツリー構造を反映します。- 入力と出力は、サーバーのスキーマとリゾルバーから推論されます。
- コンパイラーがコントラクトを強制するため、クライアントとサーバーに不整合は生じません。
次は、認証のためのコンテキストとミドルウェアです。
よくある質問
「クライアントとサーバー間の型推論」レッスンは無料ですか?
はい。「クライアントとサーバー間の型推論」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。
「クライアントとサーバー間の型推論」で何を学びますか?
コード生成なしで完全に型付けされたクライアントを取得します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「クライアントとサーバー間の型推論」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- tRPCのアーキテクチャ
- ルーターとプロシージャの定義
- クライアントとサーバー間の型推論
- ミドルウェアとコンテキスト