Ciclo For

Edoardo Midali
Edoardo Midali

Il ciclo for in TypeScript rappresenta la struttura di controllo più versatile per l’iterazione, offrendo controllo completo su inizializzazione, condizione e incremento. TypeScript potenzia questa struttura con tipizzazione statica che previene errori comuni e migliora la leggibilità del codice.

Sintassi Base e Tipizzazione

Il ciclo for tradizionale fornisce tre sezioni distinte: inizializzazione, condizione e incremento, tutte tipizzate staticamente.

// Sintassi base con tipizzazione inferita
for (let i = 0; i < 10; i++) {
  console.log(i); // i è automaticamente number
}

// Tipizzazione esplicita quando necessaria
for (let i: number = 0; i < 10; i++) {
  console.log(i);
}

// Multiple variabili con tipi differenti
for (let i = 0, j = 10; i < j; i++, j--) {
  console.log(`i: ${i}, j: ${j}`);
}

Iterazione su Array

Il ciclo for fornisce accesso diretto agli indici, essenziale quando è necessario manipolare posizioni specifiche o iterare con pattern personalizzati.

const numbers: number[] = [10, 20, 30, 40, 50];

// Iterazione standard con type safety
for (let i = 0; i < numbers.length; i++) {
  console.log(`Index ${i}: ${numbers[i]}`);
}

// Iterazione al contrario
for (let i = numbers.length - 1; i >= 0; i--) {
  console.log(numbers[i]);
}

// Iterazione con step personalizzato
for (let i = 0; i < numbers.length; i += 2) {
  console.log(`Every other: ${numbers[i]}`);
}

Strutture Multidimensionali

Il ciclo for è ideale per navigare strutture dati complesse come matrici e array annidati.

const matrix: number[][] = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];

// Iterazione annidata con type safety
for (let row = 0; row < matrix.length; row++) {
  for (let col = 0; col < matrix[row].length; col++) {
    console.log(`Matrix[${row}][${col}] = ${matrix[row][col]}`);
  }
}

Controllo di Flusso

TypeScript migliora il controllo di flusso nei cicli for attraverso type guards e label per gestione di cicli annidati.

// Break e continue con type narrowing
function processItems(items: (string | number | null)[]): number[] {
  const result: number[] = [];

  for (let i = 0; i < items.length; i++) {
    const item = items[i];

    if (item === null) continue;

    if (typeof item === "string") {
      const parsed = parseInt(item);
      if (!isNaN(parsed)) result.push(parsed);
    } else {
      if (item < 0) break;
      result.push(item);
    }
  }

  return result;
}

// Label per controllo di cicli annidati
outer: for (let i = 0; i < matrix.length; i++) {
  for (let j = 0; j < matrix[i].length; j++) {
    if (matrix[i][j] === 5) {
      break outer; // Esce da entrambi i cicli
    }
  }
}

Iterazione con Oggetti

Il ciclo for può essere utilizzato per iterare su proprietà di oggetti quando combinato con Object.keys o Object.entries.

interface UserPreferences {
  theme: "light" | "dark";
  language: string;
  notifications: boolean;
}

const preferences: UserPreferences = {
  theme: "dark",
  language: "en",
  notifications: true,
};

// Iterazione su chiavi tipizzate
const keys = Object.keys(preferences) as (keyof UserPreferences)[];
for (let i = 0; i < keys.length; i++) {
  const key = keys[i];
  console.log(`${key}: ${preferences[key]}`);
}

Performance e Ottimizzazioni

La scelta della strategia di iterazione può impattare le performance, specialmente con dataset grandi.

const largeArray: number[] = new Array(1000000).fill(0);

// Cache della lunghezza per performance migliori
const length = largeArray.length;
for (let i = 0; i < length; i++) {
  // Process element
}

// Vs accesso ripetuto a .length (meno efficiente)
for (let i = 0; i < largeArray.length; i++) {
  // Process element
}

Pattern Comuni

Il ciclo for supporta vari pattern comuni per manipolazione e trasformazione di dati.

// Pattern di trasformazione
function transform<T, R>(items: T[], fn: (item: T) => R): R[] {
  const result: R[] = [];
  for (let i = 0; i < items.length; i++) {
    result.push(fn(items[i]));
  }
  return result;
}

// Pattern di ricerca con early exit
function findIndex<T>(items: T[], predicate: (item: T) => boolean): number {
  for (let i = 0; i < items.length; i++) {
    if (predicate(items[i])) {
      return i;
    }
  }
  return -1;
}

Il ciclo for in TypeScript fornisce il massimo controllo e flessibilità per l’iterazione, combinando la potenza dell’accesso indicizzato con le garanzie di sicurezza del sistema di tipi.