型によるリレーションとJOIN
結合結果が正しく型付けされるよう、リレーションをモデル化します。
「型によるリレーションとJOIN」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。
型付きリレーションとネストされた結果
実際のスキーマにはリレーションがあります。たとえば、ユーザーは複数の投稿を持ち、投稿は1人のユーザーに属します。型安全なORMでは、これらのリレーションを宣言すると、リレーショナルクエリから正しくネストされた型付きの結果を返せます。
リレーションの宣言
テーブルと併せて、それらの接続方法を記述するリレーションオブジェクトを定義します。このメタデータが、SQLの生成と結果の型の両方を支えます。
import { relations } from "drizzle-orm";
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));リレーショナルクエリ
クエリAPIでは、with を使って関連する行を取得できます。結果では、関連データがリレーション名の下にネストされます。
const result = await db.query.users.findMany({
with: { posts: true },
});
// result: (User & { posts: Post[] })[]oneとmanyが型を決める
many リレーションは配列を返し、one リレーションは単一のオブジェクト(またはnull)を返します。ネストされた型は、宣言した多重度に対応します。
const r = await db.query.posts.findMany({
with: { author: true },
});
// r: (Post & { author: User })[] // author is a single objectリレーション内のカラム選択
親の行とネストされた行の両方を絞り込めます。結果の型は、それぞれの階層で独立して絞り込まれます。
const r = await db.query.users.findMany({
columns: { id: true, name: true },
with: {
posts: { columns: { title: true } },
},
});
// r: { id: number; name: string; posts: { title: string }[] }[]型付きカラムを使った手動JOIN
低レベルのJOINも型安全です。JOINの条件では型付きカラム参照を使い、selectによって平坦化された結果の形が決まります。
const rows = await db
.select({ author: users.name, title: posts.title })
.from(posts)
.innerJoin(users, eq(users.id, posts.authorId));
// rows: { author: string; title: string }[]left joinがnull許容性を導入する
LEFT JOINでは右側の行が存在しないことがあるため、結合されたカラムは結果の型でnull許容になります。ORMがこれを自動的に反映します。
const rows = await db
.select({ name: users.name, title: posts.title })
.from(users)
.leftJoin(posts, eq(posts.authorId, users.id));
// rows: { name: string; title: string | null }[]ネストされた結果と平坦な結果
リレーショナルクエリ(findMany + with)はネストされたオブジェクトを返し、手動JOINは平坦な行を返します。オブジェクトグラフが必要ならネストされた結果を、表形式の射影が必要なら平坦な結果を選んでください。
ネストの型付け方法
リレーションのメタデータは型レベルで読み取られます。クエリの型は、ベースとなる行に、要求されたリレーションをキーとするオブジェクトを交差させます。各キーの型は、多重度に応じて配列型または単一型になります。
type WithPosts = User & { posts: Post[] };
// "many" -> Post[], "one" -> User (or User | null for optional)深くネストされたリレーション
リレーションは組み合わせられます。リレーションのリレーションを要求することもでき、型も同じ深さまで自動的に推論されてネストされます。
await db.query.users.findMany({
with: { posts: { with: { comments: true } } },
});
// User & { posts: (Post & { comments: Comment[] })[] }なぜ重要なのか
ネストされたJOIN結果を手作業で型付けすると、間違いが起こりやすく、スキーマとのずれも生じます。宣言したリレーションから型を導出すれば、オブジェクトグラフの型とSQLを常に同期できます。そのため、リレーション名の変更は本番環境での予期せぬ問題ではなく、コンパイルエラーになります。
理解度チェック
型付きリレーションとJOINについて、理解度を確認しましょう。
まとめ
リレーションを宣言し、ORMにネストされた型付きの結果を生成させました。many は配列を返し、one は単一のオブジェクトを返します。部分選択では各階層が絞り込まれ、LEFT JOINではnull許容性が導入され、深くネストされたリレーションも組み合わせられます。リレーションのメタデータがSQLと結果の型の両方を制御するため、両者の同期が保たれます。
AI チューターと学ぶ TypeScript — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 101
- レッスン
- 352
よくある質問
「型によるリレーションとJOIN」レッスンは無料ですか?
はい。「型によるリレーションとJOIN」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。
「型によるリレーションとJOIN」で何を学びますか?
結合結果が正しく型付けされるよう、リレーションをモデル化します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「型によるリレーションとJOIN」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- スキーマから型へのマッピング
- 型安全なクエリ構築
- クエリ結果の形状推論
- 型によるリレーションとJOIN