TypeScript で深くネストされたデータ構造を扱う場合、これらの構造を変換するユーティリティ型を作成するのが一般的なタスクです。ただし、再帰型は強力ですが、独自の課題も伴います。
そのような課題の 1 つは、再帰の深さを効果的に制御して、型の計算が TypeScript の機能を超えないようにすることです。この記事では、型レベルの数値をインクリメントおよびデクリメントする一般的なアプローチを検討し、その制限を特定し、適切な Increment および Decrement 型を使用して再帰の深さを管理するための堅牢なソリューションを紹介します。
制限をよりよく理解するために、型レベルで数値を増減するときによく使用される素朴なアプローチを見てみましょう。
type Prev = [never, 0, 1, 2, 3, 4]; type Next = [1, 2, 3, 4, 5, 6]; type MinusOne = Prev[5]; // ? 4 type PlusOne = Next[5]; // ? 6
深くネストされたオブジェクトタイプがあり、すべての
を作成したいとします。
指定されたレベルまではオプションのプロパティ:
type DeepObject = { a: number; b: { c: string; d: { e: boolean; f: { g: string; h: { i: number; j: { k: string; }; }; }; }; }; };
単純なハードコーディングされたアプローチでは、プロパティがオプションになる深さを管理することは次のようになります:
type Prev = [never, 0, 1, 2, 3, 4]; type DeepOptional< T, Limit extends number = 1 > = Limit extends never ? never : { [K in keyof T]?: T[K] extends object ? DeepOptional<T[K], Prev[Limit]> : T[K]; };
説明:
使用例:
type NewDeepObject = DeepOptional<DeepObject, 3>; // Result: // { // a?: number; // b?: { // c?: string; // d?: { // e?: boolean; // f?: { // g: string; // h: { // i: number; // j: { // k: string; // }; // }; // }; // }; // }; // }; type NewDeepObject = DeepOptional<DeepObject, 1>; // Result: // { // a?: number; // b?: { // c: string; // d: { // e: boolean; // f: { // g: string; // h: { // i: number; // j: { // k: string; // }; // }; // }; // }; // }; // };
事前定義された配列の制限を克服するには、タプル操作を使用して、動的にスケーリングするタイプセーフなインクリメントおよびデクリメント操作を作成できます。
type Prev = [never, 0, 1, 2, 3, 4]; type Next = [1, 2, 3, 4, 5, 6]; type MinusOne = Prev[5]; // ? 4 type PlusOne = Next[5]; // ? 6
type DeepObject = { a: number; b: { c: string; d: { e: boolean; f: { g: string; h: { i: number; j: { k: string; }; }; }; }; }; };
type Prev = [never, 0, 1, 2, 3, 4]; type DeepOptional< T, Limit extends number = 1 > = Limit extends never ? never : { [K in keyof T]?: T[K] extends object ? DeepOptional<T[K], Prev[Limit]> : T[K]; };
type NewDeepObject = DeepOptional<DeepObject, 3>; // Result: // { // a?: number; // b?: { // c?: string; // d?: { // e?: boolean; // f?: { // g: string; // h: { // i: number; // j: { // k: string; // }; // }; // }; // }; // }; // }; type NewDeepObject = DeepOptional<DeepObject, 1>; // Result: // { // a?: number; // b?: { // c: string; // d: { // e: boolean; // f: { // g: string; // h: { // i: number; // j: { // k: string; // }; // }; // }; // }; // }; // };
これらのユーティリティ タイプを、より複雑な現実世界の問題、つまりオブジェクトのプロパティを特定の深さまでオプションにする方法にどのように適用できるかを調べてみましょう。
深くネストされたオブジェクトタイプがあり、すべての
を作成したいとします。
指定されたレベルまではオプションのプロパティ:
type Length<T extends any[]> = (T extends { length: number } ? T["length"] : never) & number;
単純なハードコーディングされたアプローチでは、プロパティがオプションになる深さを管理するのは複雑になります。タイプセーフな DeepOptional ユーティリティがこれを解決する方法は次のとおりです:
DeepOptional の実装
type TupleOf<N extends number, T extends unknown[] = []> = Length<T> extends N ? T : TupleOf<N, [...T, unknown]>;
説明:
使用例:
type Pop<T extends any[]> = T extends [...infer U, unknown] ? U : never;
medusajs では、複雑な技術的課題を克服するための最も効率的で革新的なソリューションを見つけることに全力で取り組んでいます。タプルベースの Increment 型と Decrement 型を利用することで、基本的な型レベルの操作の制限を超えて、スケーラブルでタイプセーフなユーティリティを作成できます。この方法は、再帰の深さの管理を簡素化するだけでなく、TypeScript の型チェック制限を超えることなく、複雑な型操作に必要な柔軟性を維持することも保証します。
以上がTypeScript の再帰型をマスターする: 深さの制限を適切に処理するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。