0Pricing
TypeScript Academy · Lezione

Interfacce fluenti con i tipi

Concateni metodi tenendo traccia dello stato accumulato nei tipi.

Interfacce fluenti con i tipi è una lezione TypeScript Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento TypeScript Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso TypeScript Academy include 4 lezioni in totale.

Tenere traccia di ciò che è stato impostato

Un builder semplice permette di chiamare build() in qualsiasi momento, anche quando mancano campi obbligatori. Possiamo fare di meglio tenendo traccia dello stato accumulato nel sistema dei tipi tramite un parametro di tipo generico.

Un parametro di tipo per lo stato

Assegniamo al builder un tipo generico S che registra le chiavi già fornite. A ogni chiamata di metodo, ampliamo S per includere una nuova chiave.

class Builder<S> {
  // S is a record of keys set so far, e.g. {} or { url: string }
  private data: Record<string, unknown> = {};
}

Ogni metodo aggiunge una chiave

Un setter restituisce un nuovo builder tipizzato il cui S include la chiave appena aggiunta. Il runtime memorizza il valore; il tipo viene ampliato di conseguenza.

  set<K extends string, V>(key: K, value: V): Builder<S & Record<K, V>> {
    this.data[key] = value;
    return this as unknown as Builder<S & Record<K, V>>;
  }

Il trucco dell'intersezione

L'espressione S & Record<K, V> interseca lo stato precedente con la nuova chiave. Dopo due chiamate, il tipo conosce con precisione entrambe le chiavi.

type Empty = {};
type AfterUrl = Empty & Record<"url", string>;
type AfterBoth = AfterUrl & Record<"method", string>;
// AfterBoth = { url: string; method: string }

Un builder fluente concreto

Qui un builder per le richieste propaga la struttura accumulata attraverso ogni chiamata. Il compilatore sa sempre con precisione quali campi esistono.

class Req<S> {
  private d: Record<string, unknown> = {};
  url(u: string): Req<S & { url: string }> {
    this.d.url = u; return this as any;
  }
  method(m: string): Req<S & { method: string }> {
    this.d.method = m; return this as any;
  }
}

Il tipo si arricchisce concatenando le chiamate

Ogni chiamata nella catena produce un tipo di builder più specifico. Passando il mouse sul risultato nell'editor si può visualizzare lo stato accumulato.

const partial = new Req<{}>().url("/x");
// type: Req<{ url: string }>
const full = partial.method("POST");
// type: Req<{ url: string; method: string }>

Perché tenere traccia dello stato?

Quando il tipo contiene l'insieme delle chiavi fornite, possiamo imporre in seguito che build() venga compilato solo quando sono presenti le chiavi obbligatorie. Il parametro di stato è il fondamento di questa garanzia.

Leggere la struttura accumulata

È possibile estrarre la struttura accumulata per esaminarla. In questo modo si conferma che il tipo del builder riflette esattamente ciò che è stato configurato.

type StateOf<T> = T extends Req<infer S> ? S : never;
type S1 = StateOf<Req<{ url: string }>>; // { url: string }

Il runtime resta semplice

Tutta la complessità risiede nei tipi. A runtime, ogni setter si limita a memorizzare un valore in un oggetto. I cast (as any) collegano l'oggetto a runtime al tipo più ricco verificato in fase di compilazione.

const r = new Req<{}>().url("/users").method("GET");
console.log("configured url and method");

Lo stato generico come registro

Si può pensare a S come a un registro di ciò che è stato impostato. I metodi aggiungono voci; il passaggio di build potrà poi leggere il registro per decidere se la costruzione è consentita.

Compromessi

Tenere traccia dello stato a livello di tipo offre un feedback preciso nell'IDE e impedisce le build incomplete, al costo di alcuni cast e di generics più avanzati. Il vantaggio è notevole per le API utilizzate da molte persone.

Verifica rapida

Una verifica rapida su questa lezione.

Riepilogo

Un builder fluente tipizzato mantiene un parametro di stato generico S. Ogni setter interseca S con la nuova chiave (S & Record<K, V>) e restituisce un builder più specifico, fornendo al compilatore un registro preciso dei campi configurati.

Domande Frequenti

La lezione «Interfacce fluenti con i tipi» è gratuita?

Sì — il testo completo di «Interfacce fluenti con i tipi» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso TypeScript Academy, passa a CoddyKit PRO. Il corso TypeScript Academy include 4 lezioni in totale.

Cosa imparerò in «Interfacce fluenti con i tipi»?

Concateni metodi tenendo traccia dello stato accumulato nei tipi. Eserciti TypeScript Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare TypeScript Academy?

Non è richiesta alcuna esperienza precedente. TypeScript Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Interfacce fluenti con i tipi»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione TypeScript Academy?

Sì. Ogni lezione TypeScript Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Basi del Builder Pattern
  2. Interfacce fluenti con i tipi
  3. Imporre i passaggi obbligatori
  4. Builder immutabili
← Torna a TypeScript Academy