Menu

TypeScript for-Schleife, forEach, for...of und for...in

Alle Schleifenarten in TypeScript und welche Typen sie liefern: die klassische for-Schleife, for...of über Arrays, Maps und Strings, for...in und seine String-Schlüssel, forEach (kein break, kein await), typisierte Schleifen über Objektschlüssel und while.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

TypeScript hat dieselben Schleifen wie JavaScript: for, for...of, for...in, while, do...while und die Array-Methode forEach. TypeScript ergänzt die Typen: Die Schleifenvariable von for...of hat den Elementtyp, und ein Schlüssel in for...in ist immer ein string.

Für die meisten Schleifen über Arrays ist for...of die erste Wahl: Es liest sich klar, unterstützt break, continue und await und braucht keine Annotationen.

Die klassische for-Schleife

for (init; condition; update) ist die Schleife zum Zählen, für Schritte größer als eins oder um rückwärts zu laufen. TypeScript leitet den Zähler aus seinem Startwert ab.

Deklariere den Zähler mit let, nicht mit var. Mit let bekommt jeder Durchlauf eine eigene Bindung, sodass ein in der Schleife erzeugter Callback den Wert dieses Durchlaufs sieht.

for...of: Werte von Arrays, Strings und Maps

for...of funktioniert mit allem, was iterierbar ist, und die Schleifenvariable bekommt den passenden Typ. Um auch den Index zu erhalten, durchläufst du array.entries(), das [index, value]-Tupel liefert.

break verlässt die Schleife und continue springt zum nächsten Element, genau wie in einer for-Schleife. Die Details zur Laufzeit (Iterables, Generatoren) stehen auf der JavaScript-Seite zu for...of und for...in.

forEach: kein break, kein await

forEach ruft für jedes Element eine Funktion auf und gibt undefined zurück. Die Parameter des Callbacks werden vom Array her typisiert, Annotationen sind also nicht nötig. Zwei Dinge kann es nicht:

  • Früh aufhören. break im Callback ist der Compilerfehler TS1107, Jump target cannot cross function boundary. Ein return beendet nur den aktuellen Aufruf und wirkt daher wie continue.
  • Auf asynchrone Arbeit warten. forEach ignoriert das Promise, das ein async-Callback zurückgibt.

Die async-Falle übersieht man leicht, weil sie ohne Warnung kompiliert:

Die forEach-Callbacks enden in der Reihenfolge der Timer (10, 20, 30), nachdem die Schleife längst weitergelaufen ist. Die Version mit for...of führt sie nacheinander aus. Für parallele Arbeit, auf die du trotzdem wartest, nimm await Promise.all(items.map(async (item) => { ... })).

for...in: Schlüssel sind Strings

for...in durchläuft die aufzählbaren Eigenschaftsnamen eines Objekts. Der Typ des Schlüssels ist immer string, selbst bei Arrays, wo die Schlüssel die Indizes als Strings sind. Das macht den Indexzugriff auf ein typisiertes Objekt umständlich:

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 typisiert den Schlüssel absichtlich als string: Zur Laufzeit kann ein Objekt mehr Eigenschaften haben, als sein Typ aufführt (strukturelle Typisierung erlaubt zusätzliche), und for...in durchläuft auch geerbte aufzählbare Eigenschaften. Es kann also nicht versprechen, dass der Schlüssel "name" | "age" ist. Die Lösungen stehen im nächsten Abschnitt. Verwende for...in bei Arrays überhaupt nicht.

Schlüssel und Werte eines Objekts durchlaufen

Object.entries liefert [key, value]-Paare und ist der übliche Weg, über ein Objekt zu iterieren. Object.keys gibt aus demselben Grund wie for...in string[] zurück. Wenn du weißt, dass das Objekt keine zusätzlichen Schlüssel hat, setze eine Assertion auf den Schlüsseltyp.

Für Daten, deren Schlüssel vorher nicht bekannt sind, typisierst du das Objekt als Record<string, number> oder nutzt eine Map; beides wird auf der Seite zum Dictionary behandelt.

while und do...while

while prüft seine Bedingung vor jedem Durchlauf; do...while führt den Rumpf einmal aus, bevor es prüft. Sie passen zu Schleifen, die keine Sammlung durchlaufen, etwa Lesen, bis eine Bedingung erfüllt ist. Narrowing funktioniert darin: Nach einer Prüfung !== undefined in der Bedingung ist die Variable im Rumpf eingeengt.

Labels, break und continue in verschachtelten Schleifen

Ein einfaches break verlässt nur die innerste Schleife. Um eine äußere Schleife zu verlassen, gibst du ihr ein Label und nennst es:

Welche Schleife wofür

ZielSchleife
Jedes Element eines Arraysfor (const x of arr)
Element und Indexfor (const [i, x] of arr.entries()) oder arr.forEach((x, i) => ...)
Früh aufhörenfor...of mit break oder find, some, every
Jeden Schritt abwartenfor...of mit await darin
Ein neues Array bauenmap, filter (keine Schleife)
Zählen oder in n-Schritten gehenfor (let i = 0; ...; i += n)
Schlüssel und Werte eines Objektsfor (const [k, v] of Object.entries(obj))
Einträge einer Mapfor (const [k, v] of map)
Bis eine Bedingung erfüllt istwhile

Häufig gestellte Fragen

Wie schreibt man eine for-Schleife in TypeScript?

Genau wie in JavaScript: for (let i = 0; i < 5; i++) { ... }; TypeScript leitet i als number ab. Um die Elemente eines Arrays zu durchlaufen, ist for (const item of items) kürzer, und item bekommt den Elementtyp des Arrays.

Wie breche ich in TypeScript aus forEach aus?

Gar nicht: break im Callback ist der Compilerfehler TS1107 (Jump target cannot cross function boundary), und return beendet nur den aktuellen Callback-Aufruf, wie continue. Nimm for...of mit break oder some/find/every, die von sich aus früh aufhören.

Was ist der Unterschied zwischen for...of und for...in in TypeScript?

for...of durchläuft die Werte eines Iterables (Array-Elemente, Zeichen eines Strings, Map-Einträge) mit ihren echten Typen. for...in durchläuft die aufzählbaren Eigenschaftsschlüssel eines Objekts, immer als string typisiert, Array-Indizes eingeschlossen, ebenfalls als Strings. Nimm for...of für Arrays und Object.entries für Objekte.

Wie durchlaufe ich in TypeScript die Schlüssel und Werte eines Objekts?

Mit for (const [key, value] of Object.entries(obj)). key ist ein string und value die Union der Eigenschaftstypen. Brauchst du key als keyof typeof obj, setze eine Assertion: (Object.keys(obj) as (keyof typeof obj)[]), denn TypeScript typisiert Object.keys absichtlich als string[].

Kann man await in forEach verwenden?

Es kompiliert, aber forEach wartet nicht auf die Promises, die der Callback zurückgibt, also endet die Schleife, bevor die Arbeit erledigt ist. Nimm for...of mit await darin für sequenzielle Arbeit oder await Promise.all(items.map(async (x) => ...)), um sie parallel auszuführen.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S