Heim > Web-Frontend > js-Tutorial > Beherrschen rekursiver Typen in TypeScript: Eleganter Umgang mit Tiefenbeschränkungen

Beherrschen rekursiver Typen in TypeScript: Eleganter Umgang mit Tiefenbeschränkungen

Susan Sarandon
Freigeben: 2024-11-23 04:43:19
Original
193 Leute haben es durchsucht

Mastering Recursive Types in TypeScript: Handling Depth Limitations Gracefully

Einführung

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.

? Das Problem mit grundlegenden Zahlenoperationen auf Typebene

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
Nach dem Login kopieren
Nach dem Login kopieren

? Problemszenario: Tief verschachtelte optionale Eigenschaften

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;
          };
        };
      };
    };
  };
};
Nach dem Login kopieren
Nach dem Login kopieren

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];
    };
Nach dem Login kopieren
Nach dem Login kopieren

Erklärung:

  • DeepOptional macht Eigenschaften bis zum Limit optional.
  • Der Grenzwert wird verwendet, um den dekrementierten Wert aus dem statischen Tupel abzurufen.

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;
//           };
//         };
//       };
//     };
//   };
// };
Nach dem Login kopieren
Nach dem Login kopieren

✋ Probleme mit diesem Ansatz

  • Begrenzter Bereich: Dieser Ansatz ist nur so flexibel wie die vordefinierten Arrays Prev und Next. Wenn Sie Zahlen über die Länge dieser Arrays hinaus erhöhen oder verringern müssen, müssen Sie diese manuell erweitern, was umständlich und fehleranfällig ist.
  • Skalierbarkeit: Da sich Ihre Anforderungen weiterentwickeln, wird die Verwaltung dieser Arrays immer komplexer, sodass dieser Ansatz für größere Typoperationen unpraktisch ist.

? Eine robustere Lösung: Tupelbasierte Inkrement- und Dekrementtypen

Um die Einschränkungen vordefinierter Arrays zu überwinden, können wir Tupelmanipulation verwenden, um typsichere Inkrementierungs- und Dekrementierungsoperationen zu erstellen, die dynamisch skalieren.

?️ Wichtige Bausteine

  • Length Utility: Ein Typ zum Ermitteln der Länge eines Tupels:
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
Nach dem Login kopieren
Nach dem Login kopieren
  • TupleOf: Ein Typ, der ein Tupel aus N Elementen generiert:
type DeepObject = {
  a: number;
  b: {
    c: string;
    d: {
      e: boolean;
      f: {
        g: string;
        h: {
          i: number;
          j: {
            k: string;
          };
        };
      };
    };
  };
};
Nach dem Login kopieren
Nach dem Login kopieren
  • Pop Utility: Ein Typ, der das letzte Element eines Tupels entfernt:
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];
    };
Nach dem Login kopieren
Nach dem Login kopieren
  • Inkrementieren und Dekrementieren:
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;
//           };
//         };
//       };
//     };
//   };
// };
Nach dem Login kopieren
Nach dem Login kopieren

? Anwenden von Inkrement und Dekrement: Ein praktisches Beispiel

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.

Problemszenario: Tief verschachtelte optionale Eigenschaften

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;
Nach dem Login kopieren

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]>;
Nach dem Login kopieren

Erklärung:

  • DeepOptional macht Eigenschaften bis zum Limit optional.
  • Der Typ erhöht CurrentLevel rekursiv, bis er mit Limit übereinstimmt. An diesem Punkt stoppt er die Rekursion und gibt T zurück.
  • Das Inkrement gewährleistet eine typsichere Rekursion ohne manuelle Array-Zuordnungen.

Beispielverwendung:

type Pop<T extends any[]> = T extends [...infer U, unknown] ? U : never;
Nach dem Login kopieren

?️ Fazit

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage