TypeScript'te JavaScript'teki döngülerin aynısı vardır: for, for...of, for...in, while, do...while ve dizi metodu forEach. TypeScript'in eklediği şey tiplerdir: bir for...of döngüsünün değişkeni eleman tipine sahiptir ve bir for...in anahtarı her zaman string olur.
Dizi döngülerinin çoğunda ilk tercih for...of olmalıdır: kolay okunur, break, continue ve await destekler ve hiçbir tip notasyonu gerektirmez.
Klasik for Döngüsü
for (init; condition; update), saymak, birden fazla adım atlamak ya da geriye doğru ilerlemek için kullanılan döngüdür. TypeScript sayacın tipini başlangıç değerinden çıkarır.
Sayacı var ile değil let ile bildirin. let ile her iterasyon kendi bağlamasını alır, böylece döngüde oluşturulan bir callback o iterasyonun değerini görür.
for...of: Dizilerin, String'lerin ve Map'lerin Değerleri
for...of iterable olan her şey üzerinde çalışır ve döngü değişkeni karşılık gelen tipi alır. İndeksi de almak için [index, value] tuple'ları üreten array.entries() üzerinde döngü kurun.
break döngüden çıkar, continue ise bir sonraki elemana geçer; tıpkı bir for döngüsündeki gibi. Çalışma zamanı ayrıntıları (iterable'lar, generator'lar) JavaScript'in for...of ve for...in sayfasındadır.
forEach: break Yok, await Yok
forEach her eleman için bir fonksiyon çağırır ve undefined döndürür. Callback'in parametreleri diziden tiplenir, bu yüzden notasyon gerekmez. Yapamadığı iki şey vardır:
- Erken durmak. Callback içindeki
breakbir derleme hatasıdır, TS1107:Jump target cannot cross function boundary.Birreturnyalnızca o anki çağrıyı bitirir, yanicontinuegibi davranır. - Async işi beklemek.
forEach, birasynccallback'in döndürdüğü promise'i yok sayar.
Async tuzağını gözden kaçırmak kolaydır, çünkü hiçbir uyarı olmadan derlenir:
forEach callback'leri, döngü çoktan ilerledikten sonra timer sırasıyla (10, 20, 30) biter. for...of sürümü onları sırayla çalıştırır. Yine de beklediğiniz paralel iş için await Promise.all(items.map(async (item) => { ... })) kullanın.
for...in: Anahtarlar String'dir
for...in bir nesnenin sayılabilir özellik adları üzerinde döner. Anahtarın tipi her zaman string olur; anahtarların string olarak indeksler olduğu dizilerde bile. Bu da tipli bir nesneyi indekslemeyi zahmetli hâle getirir:
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 anahtarı bilerek string olarak tipler: çalışma zamanında bir nesnenin tipinin listelediğinden daha fazla özelliği olabilir (yapısal tipleme fazladan özelliklere izin verir) ve for...in miras alınan sayılabilir özellikleri de dolaşır. Bu yüzden anahtarın "name" | "age" olduğunu garanti edemez. Çözümler bir sonraki bölümde. Dizilerde for...in kullanmaktan tamamen kaçının.
Bir Nesnenin Anahtarları ve Değerleri Üzerinde Döngü
Object.entries, [key, value] çiftleri verir ve bir nesne üzerinde döngü kurmanın olağan yoludur. Object.keys, for...in ile aynı sebepten string[] döndürür; bu yüzden nesnenin fazladan anahtarı olmadığını bildiğinizde anahtar tipi için assertion yapın.
Anahtarları önceden bilinmeyen veriler için nesneyi bir Record<string, number> olarak tipleyin ya da bir Map kullanın; ikisini de dictionary sayfası ele alır.
while ve do...while
while her geçişten önce koşulunu kontrol eder; do...while ise kontrol etmeden önce gövdeyi bir kez çalıştırır. Bir koşul sağlanana kadar okumak gibi, bir koleksiyonu dolaşmayan döngülere uygundur. İçlerinde daraltma çalışır: koşuldaki bir !== undefined kontrolünden sonra değişken gövdede daraltılmıştır.
İç İçe Döngülerde Label, break ve continue
Düz bir break yalnızca en içteki döngüden çıkar. Dıştaki bir döngüden çıkmak için ona bir label verin ve label'ın adını yazın:
Hangi Döngü Kullanılmalı
| Amaç | Döngü |
|---|---|
| Bir dizinin her elemanı | for (const x of arr) |
| Eleman ve indeks | for (const [i, x] of arr.entries()) ya da arr.forEach((x, i) => ...) |
| Erken durmak | break ile for...of, ya da find, some, every |
| Her adımı await etmek | içinde await olan for...of |
| Yeni bir dizi oluşturmak | map, filter (döngü değil) |
| Saymak ya da n adım atlamak | for (let i = 0; ...; i += n) |
| Nesne anahtarları ve değerleri | for (const [k, v] of Object.entries(obj)) |
| Map girdileri | for (const [k, v] of map) |
| Bir koşula kadar | while |
Sıkça Sorulan Sorular
TypeScript'te for döngüsü nasıl yazılır?
JavaScript'teki gibi: for (let i = 0; i < 5; i++) { ... }; TypeScript i değişkenini number olarak çıkarır. Bir dizinin elemanlarını dolaşmak için for (const item of items) daha kısadır ve item dizinin eleman tipini alır.
TypeScript'te forEach'ten nasıl çıkarım?
Çıkamazsınız: callback içindeki break bir derleme hatasıdır, TS1107 (Jump target cannot cross function boundary), ve return yalnızca o anki callback çağrısını bitirir, continue gibi davranır. break ile for...of kullanın ya da tasarım gereği erken duran some/find/every metotlarını kullanın.
TypeScript'te for...of ile for...in arasındaki fark nedir?
for...of bir iterable'ın değerlerini (dizi elemanları, string karakterleri, Map girdileri) gerçek tipleriyle dolaşır. for...in bir nesnenin sayılabilir özellik anahtarlarını dolaşır; bunlar her zaman string olarak tiplenir ve dizi indeksleri de string olarak gelir. Diziler için for...of, nesneler için Object.entries kullanın.
TypeScript'te bir nesnenin anahtarları ve değerleri üzerinde nasıl döngü kurarım?
for (const [key, value] of Object.entries(obj)) kullanın. key bir string, value ise özellik tiplerinin union'ıdır. key değişkeninin keyof typeof obj olarak tiplenmesi gerekiyorsa assertion yapın: (Object.keys(obj) as (keyof typeof obj)[]), çünkü TypeScript Object.keys sonucunu bilerek string[] olarak tipler.
forEach içinde await kullanılabilir mi?
Derlenir, ama forEach callback'in döndürdüğü promise'leri beklemez; bu yüzden döngü iş bitmeden sona erer. Sıralı iş için içinde await olan bir for...of kullanın, paralel çalıştırmak için de await Promise.all(items.map(async (x) => ...)) kullanın.