TypeScript - null vs. undefined

Ciao, aspiranti programmatori! Oggi esploreremo un argomento entusiasmante che spesso confonde i principianti: la differenza tra null e undefined in TypeScript. Non preoccupatevi se vi sentite un po' spaesati - ricordo quando ho incontrato per la prima volta questi concetti, anche io mi grattavo la testa! Ma alla fine di questa lezione, sarete esperti nel distinguere tra questi due valori speciali. Iniziamo!

TypeScript - null vs. undefined

Cos'è null?

In TypeScript (e JavaScript), null è un valore speciale che rappresenta l'assenza intenzionale di qualsiasi valore oggetto. È come dire, "C'era suponeva essere qualcosa qui, ma ora non c'è nulla."

Ecco alcuni esempi per capire meglio:

let myPet: string | null = null;
console.log(myPet); // Output: null

// Più avanti nel codice...
myPet = "Fluffy";
console.log(myPet); // Output: Fluffy

In questo esempio, dichiariamo una variabile myPet che può essere sia una stringa che null. Inizialmente, la impostiamo su null, indicando che non abbiamo un animale domestico ancora. Più tardi, quando abbiamo un animale domestico, assegnamo il nome "Fluffy" a myPet.

Ecco un altro esempio:

function findUser(id: number): { name: string } | null {
// Immagina che stiamo cercando in un database
if (id === 1) {
return { name: "Alice" };
} else {
return null;
}
}

let user = findUser(1);
console.log(user); // Output: { name: "Alice" }

user = findUser(2);
console.log(user); // Output: null

In questo caso, la nostra funzione findUser restituisceeither un oggetto utente o null se non viene trovato alcun utente. Questo è un schema comune nella programmazione - utilizzare null per indicare che una ricerca o un'operazione non ha prodotto un risultato.

Cos'è undefined?

Ora parliamo di undefined. Questo valore speciale rappresenta una variabile che è stata dichiarata ma non ha ancora un valore assegnato. È come una scatola vuota - esiste, ma non c'è nulla dentro.

Ecco alcuni esempi per illustrare undefined:

let myName: string;
console.log(myName); // Output: undefined

// Più avanti nel codice...
myName = "John";
console.log(myName); // Output: John

function greet(name?: string) {
console.log(name);
}

greet(); // Output: undefined
greet("Alice"); // Output: Alice

Nella prima parte, dichiariamo myName ma non assegniamo un valore. TypeScript automaticamente gli assegna il valore undefined. Più tardi, assegniamo un valore, e non è più undefined.

Nella funzione greet, utilizziamo un parametro opzionale. Se chiamiamo la funzione senza fornire un argomento, il parametro name sarà undefined.

Ecco un altro scenario in cui potresti incontrare undefined:

let person = {
name: "Bob",
age: 30
};

console.log(person.name); // Output: Bob
console.log(person.job); // Output: undefined

In questo caso, person.job è undefined perché non abbiamo definito una proprietà job per il nostro oggetto person.

Null vs. Undefined: Differenze Chiave

Ora che abbiamo esplorato null e undefined separatamente, confrontiamoli fianco a fianco per capire meglio le loro differenze.

Aspetto null undefined
Significato Assenza intenzionale di qualsiasi valore oggetto Variabile dichiarata ma non assegnata un valore
Tipo Oggetto Non definito
In JSON Valido Non valido
Parametro predefinito della funzione Non utilizzato come predefinito Utilizzato come predefinito per parametri opzionali
Uguaglianza null == undefined (true), null === undefined (false) undefined == null (true), undefined === null (false)

Ecco alcuni esempi di codice per illustrare queste differenze:

// Controllo del tipo
console.log(typeof null);       // Output: "object"
console.log(typeof undefined);  // Output: "undefined"

// Serializzazione JSON
console.log(JSON.stringify({ a: null }));     // Output: {"a":null}
console.log(JSON.stringify({ a: undefined })); // Output: {}

// Parametri predefiniti della funzione
function sayHello(name: string = "World") {
console.log(`Hello, ${name}!`);
}

sayHello();        // Output: Hello, World!
sayHello(undefined); // Output: Hello, World!
sayHello(null);    // Output: Hello, null!

// Uguaglianza
console.log(null == undefined);  // Output: true
console.log(null === undefined); // Output: false

Nella pratica, la scelta tra null e undefined spesso dipende dalle preferenze personali o di squadra. Tuttavia, comprendere le differenze può aiutarti a scrivere codice più preciso e privo di bug.

Ecco un esempio finale per unire tutto:

function processUser(user: { name: string, age?: number } | null | undefined) {
if (user === null) {
console.log("User explicitly set to null");
} else if (user === undefined) {
console.log("User not provided");
} else {
console.log(`Processing user: ${user.name}, Age: ${user.age ?? "Unknown"}`);
}
}

processUser(null);                    // Output: User explicitly set to null
processUser(undefined);               // Output: User not provided
processUser({ name: "Alice" });       // Output: Processing user: Alice, Age: Unknown
processUser({ name: "Bob", age: 30 }); // Output: Processing user: Bob, Age: 30

Questa funzione dimostra come potremmo gestire null, undefined e oggetti utente validi in modo diverso in uno scenario reale.

Ecco fatto! Avete appena imparato i dettagli di null e undefined in TypeScript. Ricordate, la pratica rende perfetti, quindi non abbiate paura di sperimentare questi concetti nel vostro codice. Buon coding, e possa le vostre variabili essere sempre intenzionalmente null o undefined!

Credits: Image by storyset