TypeScript Academy · レッスン

型によるリレーションとJOIN

結合結果が正しく型付けされるよう、リレーションをモデル化します。

レッスン 4/413 ステップ

「型によるリレーションと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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. スキーマから型へのマッピング
  2. 型安全なクエリ構築
  3. クエリ結果の形状推論
  4. 型によるリレーションとJOIN
← TypeScript Academyに戻る