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
- Basi del Builder Pattern
- Interfacce fluenti con i tipi
- Imporre i passaggi obbligatori
- Builder immutabili