Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 2 de 26/14 en el curso~15 min
Lecciones del módulo (2/2)

Generics Fondamentali

I Generics (programmazione generica) sono una delle caratteristiche più potenti di TypeScript. Consentono di scrivere componenti, funzioni e interfacce flessibili e riutilizzabili che possono lavorare con diversi tipi di dati, pur mantenendo la massima sicurezza dei tipi (type safety) ed evitando l'uso di any.


Le Funzioni Generiche

Pensa a un generic come a una variabile per i tipi. Consideriamo una funzione che restituisce il valore passato come argomento:

TS
function identity<T>(arg: T): T {
  return arg;
}

La lettera T (abbreviazione di Type) è un segnaposto per il tipo. Quando chiamiamo identity, TypeScript cattura il tipo dell'argomento passato ed imposta automaticamente T a quel tipo:

TS
const str = identity<string>('Hello'); // T è string
const num = identity(42); // T è number (inferito automaticamente!)

Interfacce e Alias Generici

I generics possono essere applicati anche a interfacce e type alias per definire contenitori o strutture dati generiche:

TS
interface Box<T> {
  content: T;
}

const stringBox: Box<string> = { content: 'TypeScript' };
const numberBox: Box<number> = { content: 42 };

Più Parametri di Tipo

Possiamo definire funzioni o tipi che utilizzano molteplici variabili di tipo (es. T e U):

TS
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

Vincoli sui Generics (Generic Constraints)

Talvolta vogliamo limitare i tipi accettati da un generic. Possiamo usare la parola chiave extends per aggiungere un vincolo (constraint).

Ad esempio, se vogliamo che il tipo generico abbia sempre una proprietà length (come stringhe o array):

TS
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): void {
  console.log(arg.length); // Sicuro! Sappiamo che arg ha 'length'
}

logLength('Hello'); // Valido
logLength([1, 2, 3]); // Valido
// logLength(42); // Errore: number non ha la proprietà length!

Prova tu

Esercizio 1: Funzione Generica Identity

Ejercicio#ts.m3.l2.e1
Intentos: 0Cargando...

Completa la funzione generica identity in modo che accetti un parametro value di tipo generico T e lo restituisca senza modifiche.

Cargando editor...
Mostrar pista

Il tipo di ritorno deve essere lo stesso tipo generico T del parametro.

Solución disponible después de 3 intentos

Esercizio 2: Wrapper Generico Box

Ejercicio#ts.m3.l2.e2
Intentos: 0Cargando...

Definisci un'interfaccia generica chiamata Box che accetta un parametro di tipo T e ha una singola proprietà chiamata content di tipo T.

Cargando editor...
Mostrar pista

Usa la sintassi interface Box<T> { content: T; }.

Solución disponible después de 3 intentos

Esercizio 3: Constraint Generico

Ejercicio#ts.m3.l2.e3
Intentos: 0Cargando...

Scrivi una funzione generica chiamata getLength che accetta un parametro arg. arg deve essere vincolato ad un'interfaccia che possiede una proprietà length (numero). La funzione deve restituire arg.length.

Cargando editor...
Mostrar pista

Dichiara la funzione come getLength<T extends HasLength>(arg: T): number e ritorna arg.length.

Solución disponible después de 3 intentos

Esercizio 4: Coppia Generica Pair

Ejercicio#ts.m3.l2.e4
Intentos: 0Cargando...

Definisci un'interfaccia generica Pair<T, U> con due proprietà: first di tipo T e second di tipo U. Dopodiché, crea una funzione generica makePair che accetta first (di tipo T) e second (di tipo U) e restituisce un oggetto che implementa Pair<T, U>.

Cargando editor...
Mostrar pista

Usa la sintassi per due parametri generici Pair<T, U> e definisci makePair di conseguenza.

Solución disponible después de 3 intentos