Menu

Boucles en TypeScript : for, forEach, for...of et for...in

Toutes les façons de faire une boucle en TypeScript et les types que chacune vous donne : la boucle for classique, for...of sur les tableaux, les Maps et les chaînes, for...in et ses clés string, forEach (ni break ni await), les boucles typées sur les clés d'un objet, et while.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

TypeScript a les mêmes boucles que JavaScript : for, for...of, for...in, while, do...while, et la méthode de tableau forEach. Ce que TypeScript ajoute, ce sont les types : la variable de boucle d'un for...of a le type des éléments, et la clé d'un for...in est toujours un string.

Pour la plupart des boucles sur un tableau, for...of est le bon choix : il se lit clairement, accepte break, continue et await, et ne demande aucune annotation.

La boucle for classique

for (init; condition; update) est la boucle pour compter, avancer par pas de plus de un, ou parcourir à l'envers. TypeScript infère le compteur à partir de sa valeur initiale.

Déclarez le compteur avec let, pas var. Avec let, chaque itération a sa propre liaison, donc un callback créé dans la boucle voit la valeur de cette itération.

for...of : les valeurs des tableaux, chaînes et Maps

for...of fonctionne sur tout ce qui est itérable, et la variable de boucle reçoit le type correspondant. Pour obtenir aussi l'indice, parcourez array.entries(), qui produit des tuples [index, value].

break quitte la boucle et continue passe à l'élément suivant, exactement comme dans une boucle for. Les détails d'exécution (itérables, générateurs) se trouvent sur la page JavaScript for...of et for...in.

forEach : ni break, ni await

forEach appelle une fonction pour chaque élément et renvoie undefined. Les paramètres du callback sont typés à partir du tableau, aucune annotation n'est donc nécessaire. Deux choses lui sont impossibles :

  • S'arrêter tôt. break dans le callback est l'erreur de compilation TS1107, Jump target cannot cross function boundary. Un return ne termine que l'appel en cours, il agit donc comme continue.
  • Attendre du travail asynchrone. forEach ignore la promesse renvoyée par un callback async.

Le piège de l'asynchrone passe facilement inaperçu, car le code compile sans avertissement :

Les callbacks du forEach se terminent dans l'ordre des minuteurs (10, 20, 30), alors que la boucle est déjà passée à la suite. La version for...of les exécute l'un après l'autre. Pour un travail en parallèle que vous attendez quand même, utilisez await Promise.all(items.map(async (item) => { ... })).

for...in : les clés sont des strings

for...in parcourt les noms des propriétés énumérables d'un objet. Le type de la clé est toujours string, même pour les tableaux, dont les clés sont les indices sous forme de chaînes. Cela rend l'indexation d'un objet typé malcommode :

index.ts(5,22): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; age: number; }'.
  No index signature with a parameter of type 'string' was found on type '{ name: string; age: number; }'.

TypeScript type volontairement la clé comme string : à l'exécution, un objet peut avoir plus de propriétés que son type n'en liste (le typage structurel autorise les propriétés en trop), et for...in parcourt aussi les propriétés énumérables héritées. Il ne peut donc pas promettre que la clé vaut "name" | "age". Les solutions sont dans la section suivante. Évitez complètement for...in sur les tableaux.

Parcourir les clés et les valeurs d'un objet

Object.entries donne des paires [key, value] et c'est la façon habituelle de parcourir un objet. Object.keys renvoie string[] pour la même raison que for...in : quand vous savez que l'objet n'a pas de clés en trop, faites une assertion sur le type des clés.

Pour des données dont les clés ne sont pas connues à l'avance, typez l'objet comme un Record<string, number> ou utilisez une Map ; les deux sont couverts sur la page dictionnaire.

while et do...while

while vérifie sa condition avant chaque passage ; do...while exécute le corps une fois avant de vérifier. Elles conviennent aux boucles qui ne parcourent pas une collection, par exemple lire jusqu'à ce qu'une condition soit remplie. Le narrowing fonctionne à l'intérieur : après une vérification !== undefined dans la condition, la variable est affinée dans le corps.

Labels, break et continue dans des boucles imbriquées

Un break simple ne quitte que la boucle la plus interne. Pour quitter une boucle extérieure, donnez-lui un label et nommez ce label :

Quelle boucle utiliser

ObjectifBoucle
Chaque élément d'un tableaufor (const x of arr)
Élément et indicefor (const [i, x] of arr.entries()) ou arr.forEach((x, i) => ...)
S'arrêter tôtfor...of avec break, ou find, some, every
Attendre chaque étapefor...of avec await à l'intérieur
Construire un nouveau tableaumap, filter (pas une boucle)
Compter ou avancer par pas de nfor (let i = 0; ...; i += n)
Clés et valeurs d'un objetfor (const [k, v] of Object.entries(obj))
Entrées d'une Mapfor (const [k, v] of map)
Jusqu'à une conditionwhile

Questions fréquentes

Comment écrire une boucle for en TypeScript ?

Comme en JavaScript : for (let i = 0; i < 5; i++) { ... } ; TypeScript infère i comme number. Pour parcourir les éléments d'un tableau, for (const item of items) est plus court, et item reçoit le type des éléments du tableau.

Comment sortir d'un forEach en TypeScript ?

C'est impossible : break dans le callback est l'erreur de compilation TS1107 (Jump target cannot cross function boundary), et return ne fait que terminer l'appel en cours du callback, comme continue. Utilisez for...of avec break, ou some/find/every, qui s'arrêtent tôt par conception.

Quelle est la différence entre for...of et for...in en TypeScript ?

for...of parcourt les valeurs d'un itérable (éléments d'un tableau, caractères d'une chaîne, entrées d'une Map) avec leurs vrais types. for...in parcourt les clés de propriétés énumérables d'un objet, toujours typées string, y compris les indices d'un tableau sous forme de chaînes. Utilisez for...of pour les tableaux et Object.entries pour les objets.

Comment parcourir les clés et les valeurs d'un objet en TypeScript ?

Utilisez for (const [key, value] of Object.entries(obj)). key est un string et value est l'union des types des propriétés. Si vous avez besoin que key soit typé keyof typeof obj, faites une assertion : (Object.keys(obj) as (keyof typeof obj)[]), car TypeScript type volontairement Object.keys comme string[].

Peut-on utiliser await dans un forEach ?

Ça compile, mais forEach n'attend pas les promesses renvoyées par le callback, donc la boucle se termine avant le travail. Utilisez for...of avec await à l'intérieur pour un traitement séquentiel, ou await Promise.all(items.map(async (x) => ...)) pour l'exécuter en parallèle.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER