TypeScript - Utility Types

Ciao là, futuri maghi della programmazione! Oggi ci imbarcheremo in un viaggio emozionante attraverso il magico regno dei tipi utilità di TypeScript. Non preoccupatevi se siete nuovi alla programmazione; sarò il vostro guida amichevole, e esploreremo questi concetti insieme, passo dopo passo. Quindi, afferrate le vostre bacchette virtuali (tastiere) e tuffiamoci!

TypeScript - Utility Types

Cos'è un Tipo Utilità?

Prima di iniziare, capiamo cos'è un Tipo Utilità. Immagina di avere una cassetta degli attrezzi piena di vari attrezzi. Ogni attrezzo ti aiuta a eseguire un compito specifico più efficientemente. Questo è esattamente ciò che sono i tipi utilità in TypeScript - sono strumenti pre-costruiti che ci aiutano a manipolare e trasformare i tipi facilmente.

Ora, esaminiamo ciascuno di questi strumenti magici uno per uno!

Tipo Partial in TypeScript

Il tipo Partial è come un incantesimo che rende tutte le proprietà di un oggetto opzionali. È estremamente utile quando vuoi creare un oggetto dove non è necessario specificare tutte le proprietà.

Vediamo come funziona:

interface Mago {
nome: string;
età: number;
casa: string;
}

function aggiornaMago(mago: Mago, campiAggiornare: Partial<Mago>) {
return { ...mago, ...campiAggiornare };
}

const harryPotter: Mago = {
nome: "Harry Potter",
età: 11,
casa: "Grifondoro"
};

const harryAggiornato = aggiornaMago(harryPotter, { età: 17 });
console.log(harryAggiornato);
// Output: { nome: "Harry Potter", età: 17, casa: "Grifondoro" }

In questo esempio, Partial<Mago> ci permette di aggiornare solo l'età di Harry senza dover specificare tutte le altre proprietà. È come alzare una bacchetta e dire, "Partial Revelio!"

Tipo Required in TypeScript

Il tipo Required è l'opposto di Partial. È come lanciare un incantesimo che rende tutte le proprietà di un oggetto obbligatorie, anche se erano originariamente opzionali.

interface CreaturaMagica {
nome: string;
potere?: string;
età?: number;
}

const drago: Required<CreaturaMagica> = {
nome: "Norwegian Ridgeback",
potere: "Respiro di fuoco",
età: 2
};

// Questo causerebbe un errore:
// const unicorn: Required<CreaturaMagica> = {
//   nome: "Corno d'Argento"
// };

Qui, anche se potere e età erano opzionali nell'interfaccia originale, il tipo Required li rende obbligatori. È come dire, "Accio tutte le proprietà!"

Tipo Pick in TypeScript

Il tipo Pick ti permette di creare un nuovo tipo selezionando specifiche proprietà da un tipo esistente. È come usare un Incantesimo di Evocazione per chiamare solo le proprietà di cui hai bisogno.

interface Pozione {
nome: string;
ingredienti: string[];
tempoDiPreparazione: number;
effetto: string;
}

type EtichettaPozione = Pick<Pozione, 'nome' | 'effetto'>;

const pozionePolisucco: EtichettaPozione = {
nome: "Pozione Polisucco",
effetto: "Trasforma il bevitore in un'altra persona"
};

In questo esempio, abbiamo creato un nuovo tipo EtichettaPozione che include solo le proprietà nome e effetto dell'interfaccia Pozione. È perfetto quando hai bisogno solo di pochi dettagli specifici!

Tipo Omit in TypeScript

Il tipo Omit è l'opposto di Pick. Crea un nuovo tipo rimuovendo specifiche proprietà da un tipo esistente. Pensalo come un Incantesimo di Scomparsa su certe proprietà!

interface LibroIncantesimi {
titolo: string;
autore: string;
pagine: number;
incantesimoSegreto: string;
}

type LibroIncantesimiPubblico = Omit<LibroIncantesimi, 'incantesimoSegreto'>;

const libroIncantesimiPrincipianti: LibroIncantesimiPubblico = {
titolo: "Libro Standard degli Incantesimi, Livello 1",
autore: "Miranda Goshawk",
pagine: 250
};

Qui, abbiamo creato un tipo LibroIncantesimiPubblico che include tutte le proprietà di LibroIncantesimi tranne incantesimoSegreto. È come dire, "Mostrami tutto tranne il segreto!"

Tipo Readonly in TypeScript

Il tipo Readonly è come lanciare un incantesimo di protezione sulle tue proprietà. Rende tutte le proprietà di un tipo di sola lettura, prevenendo modifiche accidentali.

interface Bacchetta {
legno: string;
nucleo: string;
lunghezza: number;
}

const bacchettaHarry: Readonly<Bacchetta> = {
legno: "Agrifoglio",
nucleo: "Piuma di fenice",
lunghezza: 11
};

// Questo causerebbe un errore:
// bacchettaHarry.lunghezza = 12;

Con Readonly, abbiamo assicurato che una volta creata una bacchetta, le sue proprietà non possono essere cambiate. È come mettere un incantesimo indistruttibile sugli oggetti!

Tipo ReturnType in TypeScript

Il tipo ReturnType ti permette di estrarre il tipo di ritorno di una funzione. È come usare Legilimency per sbirciare dentro una funzione e vedere cosa restituisce!

function lanciaIncantesimo(nomeIncantesimo: string): { nome: string, potenza: number } {
// Logica di lancio incantesimo qui
return { nome: nomeIncantesimo, potenza: Math.random() * 100 };
}

type RisultatoIncantesimo = ReturnType<typeof lanciaIncantesimo>;

const lumos: RisultatoIncantesimo = {
nome: "Lumos",
potenza: 50
};

In questo esempio, RisultatoIncantesimo è inferito come { nome: string, potenza: number }, che è il tipo di ritorno di lanciaIncantesimo. È incredibilmente utile quando si lavora con funzioni complesse!

Tipo Record in TypeScript

Il tipo Record è un incantesimo potente che crea un tipo oggetto con una specifica chiave e tipo di valore. È come evocare una mappa magica dove definisci cosa devono essere le chiavi e i valori.

type CoppaCasa = Record<string, number>;

const puntiCasa: CoppaCasa = {
"Grifondoro": 472,
"Hufflepuff": 352,
"Ravenclaw": 426,
"Slytherin": 472
};

Qui, CoppaCasa è un tipo dove le chiavi sono stringhe (nomi delle case) e i valori sono numeri (punti). Assicura che il nostro oggetto punti delle case ha la struttura corretta.

Tipo NonNullable in TypeScript

Il tipo NonNullable è come lanciare un incantesimo per bandire i valori null e undefined. Crea un nuovo tipo escludendo null e undefined da un tipo dato.

type OggettoMagico = string | number | null | undefined;

type OggettoMagicoDefinito = NonNullable<OggettoMagico>;

const oggettoDefinito: OggettoMagicoDefinito = "Cappa d'Invisibilità";
// Questo causerebbe un errore:
// const oggettoNull: OggettoMagicoDefinito = null;

In questo esempio, OggettoMagicoDefinito è un tipo che può essere stringa o numero, ma non null o undefined. È perfetto quando vuoi assicurarti di lavorare con valori effettivi!

Foglio di Trucchi dei Tipi Utilità

Ecco una tabella di riferimento rapida per tutti i tipi utilità che abbiamo coperto:

Tipo Utilità Descrizione Esempio
Partial Rende tutte le proprietà in T opzionali Partial<Mago>
Required Rende tutte le proprietà in T obbligatorie Required<CreaturaMagica>
Pick<T, K> Crea un tipo con solo le proprietà K da T Pick<Pozione, 'nome' | 'effetto'>
Omit<T, K> Crea un tipo senza le proprietà K da T Omit<LibroIncantesimi, 'incantesimoSegreto'>
Readonly Rende tutte le proprietà in T di sola lettura Readonly<Bacchetta>
ReturnType Estrae il tipo di ritorno di una funzione T ReturnType<typeof lanciaIncantesimo>
Record<K, T> Crea un tipo oggetto con chiavi di tipo K e valori di tipo T Record<string, number>
NonNullable Crea un tipo escludendo null e undefined da T NonNullable<OggettoMagico>

E voilà, giovani maghi! Ora avete padroneggiato le basi delle magie dei tipi utilità di TypeScript. Ricordate, come ogni magia, questi tipi diventano più potenti con la pratica. Quindi, continuate a sperimentare, e presto lancerete questi tipi con la stessa facilità con cui dite "Wingardium Leviosa"!

Credits: Image by storyset