Maison > interface Web > js tutoriel > Types conditionnels récursifs

Types conditionnels récursifs

Barbara Streisand
Libérer: 2024-12-01 03:00:13
original
461 Les gens l'ont consulté

Recursive Conditional Types

Supposons que vous ayez une boucle for in et que vous réalisez soudainement que votre type de variable est une chaîne et non un type d'union littéral de chaîne. Vous obtenez donc cette vilaine erreur lorsque vous compilez votre application avec tsc, et de manière ennuyeuse, votre IDE préféré crie très probablement au sommet de sa fente :

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'.
  No index signature with a parameter of type 'string' was found on type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'.ts(7053)
Copier après la connexion

[!NOTE]

Juste pour vous montrer comment cela se fait, j'utilise os.cpus. Là, j'essaie de faire une boucle sur cpu.times qui est un objet. Vous pouvez trouver plus d'informations ici.

Voici donc le code problématique :

import { cpus } from 'os';

const logicalCoresInfo = cpus();

for (const logicalCoreInfo of logicalCoresInfo) {
  let total = 0;
  for (const type in logicalCoreInfo.times) {
    total += logicalCoreInfo.times[type];  // Darn it, TS is upset!
  }
}
Copier après la connexion

Réparer

  1. Nous devons extraire les clés à l'intérieur du logicalCoreInfo.times et en créer un nouveau type.
  2. Ensuite, nous pouvons utiliser l'assertion de type pour convaincre TS que tout va bien et que nous savons ce qui se passe ici.

Alors allons-y, pour la première partie, nous devons créer un type d'utilitaire personnalisé pour nous-mêmes, voici à quoi ressemblera notre type d'utilitaire final :

type NestedKeysOf<T, K extends PropertyKey> = T extends object
  ? {
      [TKey in keyof T]-?:
        | (TKey extends K ? keyof T[TKey] : never)
        | NestedKeysOf<T[TKey], K>;
    }[keyof T]
  : never;
Copier après la connexion

Décomposons-le :

  1. T étend l'objet ? ... : ne dit jamais à TS de parcourir de manière récursive un type d'objet imbriqué T et d'extraire les clés d'une clé spécifique à l'intérieur de T si T est un objet.
  2. [TKey in keyof T]-? est un "Mapped Type" qui est particulièrement utile ici puisque l'on ne connaît pas le nom des clés à l'intérieur de l'objet passé à ce type d'utilitaire. Ici, vous lui transmettez logicalCoreInfo ou tout autre objet, puis il parcourt les clés pour en créer un nouveau type.

    Et -? est-il là pour supprimer l'optionnalité afin que nous ayons un type d'union littéral de chaîne de toutes les clés. En d'autres termes, { keyName?: string } sera traité comme { keyName: string }.

  3. (TKey extends K ? keyof T[TKey] : never) vérifie si la clé actuelle dans l'itération correspond à la clé passée (K), si oui, elle extrait toutes les clés qu'elle contient en tant que type d'union littérale de chaîne et retournez-le. Sinon, cela ne renvoie rien.

  4. Ensuite, si l'étape 3 n'a eu aucun résultat, elle appliquera récursivement ce type d'utilitaire sur T[Tkey], de cette façon notre fonction utilitaire fonctionne également sur les objets imbriqués. Ceci est communément appelé « type conditionnel récursif ».

  5. Enfin nous lui demandons de prendre l'union de tous les types générés par le type mappé. Bref on aplatit la structure imbriquée.

Alors maintenant, il est temps de l'utiliser :

interface Person {
  name: string;
  address: {
    street: string;
    city: string;
  };
}

type KeysOfAddress = NestedKeysOf<Person, 'address'>; // "street" | "city"

// Or in our original example:
type CpuTimesKeys = NestedKeysOf<typeof logicalCoreInfo, 'times'>;
// ...
total += logicalCoreInfo.times[type as CpuTimesKeys];
// ...
Copier après la connexion

Réf

  • Clé TypeScript du type d'objet imbriqué.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal