Generici TypeScript con esempi

I generici TypeScript sono una potente funzionalità che consente di creare componenti riutilizzabili e sicuri per i tipi. I generici forniscono un modo per creare classi, funzioni e interfacce che funzionano con una varietà di tipi mantenendo una forte sicurezza per i tipi. Questo articolo ti introdurrà ai generici e ti mostrerà come usarli con esempi pratici.

Capire i generici

I generici consentono di definire un componente con un segnaposto per il tipo su cui opera. Invece di specificare un tipo concreto, si utilizza un parametro di tipo generico che può essere sostituito con qualsiasi tipo quando si utilizza il componente.

Sintassi di base

La sintassi di base per definire un tipo generico è quella di usare le parentesi angolari <> con un nome di parametro di tipo. Ecco un semplice esempio:

function identity(value: T): T {
  return value;
}

const stringIdentity = identity("Hello"); // string
const numberIdentity = identity(123); // number

In questo esempio, identity è una funzione generica che accetta un parametro value di tipo T e restituisce un valore dello stesso tipo. Il parametro di tipo T viene sostituito con il tipo effettivo quando la funzione viene chiamata.

Generici con classi

I generici possono anche essere usati con le classi per creare strutture dati flessibili e riutilizzabili. Ecco un esempio di una classe generica:

class Box {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }

  getValue(): T {
    return this.value;
  }
}

const stringBox = new Box("TypeScript");
console.log(stringBox.getValue()); // Output: TypeScript

const numberBox = new Box(42);
console.log(numberBox.getValue()); // Output: 42

In questo esempio, la classe Box è definita con un parametro di tipo generico T. La classe ha una proprietà privata value di tipo T e un metodo getValue che restituisce il valore di tipo T.

Generici con interfacce

I generici possono essere usati con le interfacce per creare interfacce flessibili e sicure per i tipi. Ecco un esempio:

interface Pair<T, U> {
  first: T;
  second: U;
}

const pair: Pair<string, number> = {
  first: "Age",
  second: 30
};

console.log(pair.first); // Output: Age
console.log(pair.second); // Output: 30

In questo esempio, l'interfaccia Pair è definita con due parametri di tipo generico T e U. L'interfaccia rappresenta una coppia di valori con tipi T e U, rispettivamente.

Generici nelle funzioni

I generici possono essere usati nelle funzioni per gestire più tipi mantenendo la sicurezza dei tipi. Ecco un esempio di una funzione generica che funziona con gli array:

function reverseArray(items: T[]): T[] {
  return items.reverse();
}

const reversedStringArray = reverseArray(["one", "two", "three"]);
console.log(reversedStringArray); // Output: ["three", "two", "one"]

const reversedNumberArray = reverseArray([1, 2, 3]);
console.log(reversedNumberArray); // Output: [3, 2, 1]

In questo esempio, la funzione reverseArray accetta un array di tipo T e restituisce un array invertito dello stesso tipo. Il parametro di tipo T assicura che la funzione funzioni con array di qualsiasi tipo mantenendo la sicurezza del tipo.

Vincoli sui generici

A volte potresti dover imporre dei vincoli sul parametro di tipo generico per assicurarti che abbia determinate proprietà. Questo si fa usando i vincoli:

function logLength(item: T): void {
  console.log(item.length);
}

logLength("Hello, TypeScript"); // Output: 16
logLength([1, 2, 3]); // Output: 3
// logLength(123); // Error: number does not have a length property

In questo esempio, la funzione logLength è vincolata ai tipi che hanno una proprietà length. Ciò consente alla funzione di accettare stringhe e array ma non numeri o altri tipi senza una proprietà length.

Conclusione

I generici in TypeScript forniscono un modo potente per creare componenti flessibili e riutilizzabili mantenendo una forte sicurezza dei tipi. Comprendendo e utilizzando i generici, puoi scrivere codice più generico e adattabile, migliorando la qualità complessiva e la manutenibilità delle tue applicazioni TypeScript.

Sperimenta i generici nei tuoi progetti per vederne i vantaggi in azione e migliorare le tue competenze di programmazione TypeScript.