0Pricing
TypeScript Academy · レッスン

DeepPartialとDeepReadonly

PartialとReadonlyの再帰版を構築します。

「DeepPartialとDeepReadonly」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。

ディープユーティリティ型を使う理由

組み込みのPartialとReadonlyは一段階にしか適用されません。ネストしたオブジェクトには、再帰的なバージョンが必要です。

interface Config {
  db: { host: string; port: number };
  app: { name: string };
}
type Shallow = Partial<Config>;
// Shallow.db is still required — only top level is optional

DeepPartial の実装

オブジェクトのプロパティを再帰的にマッピングし、それぞれをオプションにします。プロパティ値がオブジェクトの場合は、DeepPartialを再帰的に適用します。

type DeepPartial<T> = T extends object
  ? { [K in keyof T]?: DeepPartial<T[K]> }
  : T;

DeepPartial の使用例

ネストした設定型にDeepPartialを適用し、すべての階層がオプションになることを確認します。

type PartialConfig = DeepPartial<Config>;
// PartialConfig.db?: { host?: string; port?: number }

const c: PartialConfig = { db: { host: "localhost" } };
// No error — all other fields are optional

DeepReadonly の実装

ネストしたオブジェクト型に再帰的に入り、すべての深さのプロパティをreadonlyにします。

type DeepReadonly<T> = T extends object
  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
  : T;

DeepReadonly の使用例

深く凍結された設定は、どの階層でも変更できません。

type ReadonlyConfig = DeepReadonly<Config>;
const cfg: ReadonlyConfig = { db: { host: "localhost", port: 5432 }, app: { name: "my-app" } };
// cfg.db.port = 3000; // Error: readonly

ディープ型での配列の扱い

配列には特別な処理が必要です。配列を通常のオブジェクトとして扱うのではなく、要素型を再帰的にマッピングします。

type DeepPartial<T> =
  T extends (infer U)[]
    ? DeepPartial<U>[]
    : T extends object
      ? { [K in keyof T]?: DeepPartial<T[K]> }
      : T;

プリミティブ型の扱い

再帰の基底ケースでは、プリミティブ型をオブジェクトのマップ型でラップせず、そのまま返す必要があります。

type DeepReadonly<T> =
  T extends string | number | boolean | null | undefined ? T
  : T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>>
  : { readonly [K in keyof T]: DeepReadonly<T[K]> };

DeepPartial と DeepReadonly の組み合わせ

これらを組み合わせると、安全に設定をパッチするための、すべての階層で部分的かつ読み取り専用の型を作成できます。

type SafePatch<T> = DeepReadonly<DeepPartial<T>>;

パフォーマンスに関する考慮事項

非常に大きなオブジェクトに対する再帰型は、TypeScript の型チェックを遅くすることがあります。パフォーマンスが重要なコードでは、深さの制限や遅延評価を検討してください。

// For very deep schemas, consider using Zod or io-ts
// which provide runtime + compile-time deep typing

実用例: React の状態パッチ

DeepPartialは、大きな状態オブジェクトの変更された部分だけを受け取る状態パッチ関数に最適です。

function patch<T>(state: T, changes: DeepPartial<T>): T {
  return { ...state, ...changes } as T;
}

まとめ: ディープユーティリティ型

DeepPartialとDeepReadonlyは、ネストしたオブジェクトのすべての階層に修飾子を適用する再帰的なマップ型です。配列は別に処理し、プリミティブ型には基底ケースを使用します。

理解度チェック

DeepPartialの再帰における正しい基底ケースは何ですか?

学習内容

再帰的なマップ型を使ってDeepPartialとDeepReadonlyを実装しました。配列は特別なケースとして処理し、基底ケースでは常にプリミティブ型を変更せずに返します。

よくある質問

「DeepPartialとDeepReadonly」レッスンは無料ですか?

はい。「DeepPartialとDeepReadonly」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。

「DeepPartialとDeepReadonly」で何を学びますか?

PartialとReadonlyの再帰版を構築します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「DeepPartialとDeepReadonly」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. DeepPartialとDeepReadonly
  2. FlattenとUnwrapPromiseユーティリティ
  3. TupleToUnionとUnionToIntersection
  4. 型ユーティリティライブラリの公開
← TypeScript Academyに戻る