ES6+ in pratica: optional chaining e nullish coalescing

by Anastasia P.
SHARE
ES6+ in pratica: optional chaining e nullish coalescing
© Guida-HTML5.it

Introduzione

JavaScript moderno ha introdotto diversi strumenti per scrivere codice più sicuro, leggibile e conciso. Tra questi, optional chaining e nullish coalescing sono particolarmente utili quando un’applicazione lavora con dati provenienti da API, moduli di configurazione o oggetti complessi.

Quando accediamo a una proprietà annidata, possiamo incontrare valori mancanti. Ad esempio, un server potrebbe restituire un utente senza indirizzo, oppure una risposta potrebbe non contenere sempre tutti i campi previsti. Prima di queste funzionalità, era comune scrivere molte verifiche manuali:

const citta = utente &&
  utente.profilo &&
  utente.profilo.indirizzo &&
  utente.profilo.indirizzo.citta;

Questo approccio funziona, ma è verboso e rende il codice difficile da leggere. Con ES2020, parte dell’evoluzione di ES6+, possiamo usare l’operatore optional chaining ?. e l’operatore nullish coalescing ??.

In questo tutorial costruiremo un piccolo esempio che simula la visualizzazione di un profilo utente ricevuto da un servizio remoto.

Codice completo

const rispostaApi = {
  id: 42,
  nome: "Marta",
  profilo: {
    ruolo: "Frontend developer"
  },
  preferenze: {
    notifiche: false
  }
};

// Optional chaining:
// restituisce undefined se una proprietà intermedia è null o undefined.
const citta = rispostaApi.profilo?.indirizzo?.citta;

// Nullish coalescing:
// usa il valore a destra solo quando quello a sinistra è null o undefined.
const nomeVisualizzato = rispostaApi.nome ?? "Utente anonimo";
const cittaVisualizzata = citta ?? "Città non specificata";

// L´optional chaining può essere usato anche con i metodi.
const iniziali = rispostaApi.nome?.toUpperCase()?.slice(0, 2);

// Accesso sicuro a un metodo potenzialmente inesistente.
const messaggioBenvenuto = rispostaApi.messaggi?.benvenuto?.();

// Attenzione: false è un valore valido e non viene sostituito da ??.
const notificheAttive =
  rispostaApi.preferenze?.notifiche ?? true;

console.log("Nome:", nomeVisualizzato);
console.log("Città:", cittaVisualizzata);
console.log("Iniziali:", iniziali);
console.log("Messaggio:", messaggioBenvenuto);
console.log("Notifiche attive:", notificheAttive);

Spiegazione

Optional chaining con le proprietà

L’operatore ?. interrompe l’accesso a una catena di proprietà quando incontra null o undefined. In quel caso il risultato dell’espressione è undefined, invece di generare un errore.

const utente = {
  nome: "Luca",
  contatti: {
    email: "[email protected]"
  }
};

const email = utente.contatti?.email;
const telefono = utente.contatti?.telefono;
const indirizzo = utente.indirizzo?.via;

console.log(email);      // "[email protected]"
console.log(telefono);   // undefined
console.log(indirizzo);  // undefined

Senza optional chaining, l’accesso a utente.indirizzo.via causerebbe un TypeError, perché indirizzo non esiste. L’operatore è quindi molto utile quando la struttura dei dati non è completamente garantita.

Optional chaining con gli array

È possibile usare ?. anche per leggere un elemento di un array. La sintassi ?.[indice] evita errori quando l’array potrebbe mancare.

const ordine = {
  prodotti: [
    { nome: "Tastiera", prezzo: 49.90 }
  ]
};

const primoProdotto = ordine.prodotti?.[0]?.nome;
const prodottoInesistente = ordine.prodotti?.[5]?.nome;

console.log(primoProdotto);       // "Tastiera"
console.log(prodottoInesistente); // undefined

Optional chaining con le funzioni

La sintassi funzione?.() permette di chiamare una funzione solo se esiste. È utile, per esempio, quando un callback è opzionale.

function eseguiOperazione(valore, callback) {
  const risultato = valore * 2;

  // Il callback viene invocato solo se è una funzione definita.
  callback?.(risultato);
}

eseguiOperazione(5, risultato => {
  console.log("Risultato:", risultato);
});

eseguiOperazione(10); // Nessun errore

Nullish coalescing

L’operatore ?? restituisce il valore a sinistra se questo non è null e non è undefined. Altrimenti restituisce il valore predefinito a destra.

const titolo = null ?? "Titolo predefinito";
const descrizione = undefined ?? "Nessuna descrizione";

console.log(titolo);       // "Titolo predefinito"
console.log(descrizione);  // "Nessuna descrizione"

La differenza principale rispetto all’operatore OR, ||, riguarda i valori falsy come 0, false e la stringa vuota. Questi valori possono essere perfettamente validi e non devono essere sostituiti automaticamente.

const quantita = 0;
const conOr = quantita || 1;
const conNullish = quantita ?? 1;

console.log(conOr);       // 1
console.log(conNullish);  // 0

const attivo = false;
console.log(attivo || true); // true
console.log(attivo ?? true); // false

Quando si usano entrambi gli operatori nella stessa espressione, è buona pratica inserire parentesi esplicite. JavaScript non permette di mescolare direttamente ?? con || o && senza parentesi.

Best practice

  • Usa optional chaining per dati realmente opzionali. Non nascondere errori di progettazione o proprietà che dovrebbero essere sempre presenti.
  • Preferisci ?? a || quando zero, false o stringa vuota sono valori validi. È una scelta importante nei moduli di configurazione e nei form.
  • Non abusare dell’optional chaining. Se una proprietà è obbligatoria, un errore esplicito può aiutare a individuare prima un problema.
  • Combina gli operatori con nomi descrittivi. Salvare il risultato in una costante come cittaVisualizzata migliora la leggibilità.
  • Controlla la compatibilità dell’ambiente. I browser moderni e le versioni attuali di Node.js supportano queste funzionalità, ma per progetti legacy può essere necessario usare Babel o un sistema di transpiling.
  • Non usare ?. per sostituire la validazione dei dati. Quando i dati arrivano da un’API, è comunque consigliabile validarne la forma con controlli dedicati o librerie specifiche.

Riepilogo

L’optional chaining permette di accedere in modo sicuro a proprietà, elementi di array e funzioni potenzialmente mancanti. La sintassi principale è oggetto?.proprieta, mentre per gli array si può usare array?.[indice] e per le funzioni callback?.().

Il nullish coalescing consente invece di definire un valore alternativo solo quando il risultato originale è null o undefined. Questo lo rende più preciso dell’operatore || in molti casi pratici.

Usati insieme, questi strumenti rendono il codice ES6+ più robusto, soprattutto nella gestione di risposte API, configurazioni facoltative e dati annidati. La sintassi più comune è:

const valore = oggetto?.proprieta?.annidata ?? valorePredefinito;

Approfondisci con risorse ufficiali

SHARE