Bei der Arbeit mit tief verschachtelten Datenstrukturen in TypeScript ist das Erstellen von Dienstprogrammtypen zur Transformation dieser Strukturen eine häufige Aufgabe. Rekursive Typen sind zwar leistungsstark, bringen jedoch ihre eigenen Herausforderungen mit sich.
Eine dieser Herausforderungen besteht darin, die Rekursionstiefe effektiv zu steuern, um zu verhindern, dass die Typberechnung die Fähigkeiten von TypeScript überschreitet. In diesem Artikel wird ein gängiger Ansatz zum Inkrementieren und Dekrementieren von Nummern auf Typebene untersucht, seine Einschränkungen identifiziert und eine robuste Lösung für die Verwaltung der Rekursionstiefe mithilfe der richtigen Inkrementierungs- und Dekrementierungstypen vorgestellt.
Um die Einschränkungen besser zu verstehen, schauen wir uns einen naiven Ansatz an, der häufig beim Erhöhen oder Verringern von Zahlen auf Typebene verwendet wird:
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
Angenommen, Sie haben einen tief verschachtelten Objekttyp und möchten alles
machen
Eigenschaften optional bis zu einer bestimmten Ebene:
type DeepObject = { a: number; b: { c: string; d: { e: boolean; f: { g: string; h: { i: number; j: { k: string; }; }; }; }; }; };
Mit einem naiven, hartcodierten Ansatz würde die Verwaltung der Tiefe, ab der Eigenschaften optional werden, folgendermaßen aussehen:
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]; };
Erklärung:
Beispielverwendung:
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; // }; // }; // }; // }; // }; // };
Um die Einschränkungen vordefinierter Arrays zu überwinden, können wir Tupelmanipulation verwenden, um typsichere Inkrementierungs- und Dekrementierungsoperationen zu erstellen, die dynamisch skalieren.
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; // }; // }; // }; // }; // }; // };
Lassen Sie uns untersuchen, wie diese Dienstprogrammtypen auf ein komplexeres reales Problem angewendet werden können: Eigenschaften eines Objekts bis zu einer bestimmten Tiefe optional zu machen.
Angenommen, Sie haben einen tief verschachtelten Objekttyp und möchten alles
machen
Eigenschaften optional bis zu einer bestimmten Ebene:
type Length<T extends any[]> = (T extends { length: number } ? T["length"] : never) & number;
Mit einem naiven, fest codierten Ansatz wäre es komplex, die Tiefe zu verwalten, in der Eigenschaften optional werden. So kann ein typsicheres DeepOptional-Dienstprogramm dieses Problem lösen:
DeepOptional implementieren
type TupleOf<N extends number, T extends unknown[] = []> = Length<T> extends N ? T : TupleOf<N, [...T, unknown]>;
Erklärung:
Beispielverwendung:
type Pop<T extends any[]> = T extends [...infer U, unknown] ? U : never;
Bei medusajs sind wir bestrebt, die effizientesten und innovativsten Lösungen zur Bewältigung komplexer technischer Herausforderungen zu finden. Durch die Nutzung tupelbasierter Inkrementierungs- und Dekrementierungstypen können Sie die Einschränkungen grundlegender Vorgänge auf Typebene überwinden und skalierbare, typsichere Dienstprogramme erstellen. Diese Methode vereinfacht nicht nur die Verwaltung der Rekursionstiefe, sondern stellt auch sicher, dass Sie die für komplexe Typoperationen erforderliche Flexibilität beibehalten, ohne die Typprüfungsgrenzen von TypeScript zu überschreiten.
Das obige ist der detaillierte Inhalt vonBeherrschen rekursiver Typen in TypeScript: Eleganter Umgang mit Tiefenbeschränkungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!