Menu

Utility types in TypeScript: la lista completa con esempi

Tutti gli utility types integrati di TypeScript in un unico posto: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ReturnType, Awaited, i tipi per le stringhe e altri, ognuno con una descrizione di una riga e un esempio eseguibile.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Gli utility types sono tipi generici integrati in TypeScript che trasformano un tipo in un altro. Invece di scrivere un secondo tipo User con tutti i campi opzionali, scrivi Partial<User>; invece di copiare tre campi, Pick<User, "id" | "name">. Sono globali, quindi non serve importarli.

Quando User cambia, tutti e quattro i tipi derivati si adeguano. La libreria standard di TypeScript (lib.es5.d.ts) dichiara 22 utility types. Le sezioni seguenti li elencano tutti, raggruppati in base al genere di tipo su cui lavorano, con un link alla pagina dettagliata quando esiste.

Tipi oggetto: Partial, Required, Readonly, Pick, Omit, Record

Utility typeCosa faEsempio
Partial<T>rende opzionali tutte le proprietàPartial<User> per i dati di un aggiornamento
Required<T>rende obbligatorie tutte le proprietà (toglie ?)Required<Config> dopo aver applicato i valori predefiniti
Readonly<T>rende readonly tutte le proprietàReadonly<State>
Pick<T, K>conserva solo le chiavi KPick<User, "id" | "name">
Omit<T, K>toglie le chiavi KOmit<User, "password">
Record<K, V>un tipo oggetto con chiavi K e valori VRecord<"en" | "de", string>

Required<T> è l'opposto di Partial<T>; la pagina su Partial tratta entrambi, compreso l'undefined esplicito che uno spread come questo lascia passare.

Tipi unione: Exclude, Extract, NonNullable

Utility typeCosa faEsempio
Exclude<U, M>toglie i membri dell'unione assegnabili a MExclude<"a" | "b" | "c", "a"> è "b" | "c"
Extract<U, M>conserva i membri dell'unione assegnabili a MExtract<string | number, number> è number
NonNullable<T>toglie null e undefinedNonNullable<string | null> è string

Questi tre lavorano sulle unioni, non sugli oggetti. È questa la differenza chiave rispetto a Pick e Omit, che ricevono un tipo oggetto e una lista delle sue chiavi.

Tipi di funzioni e classi: Parameters, ReturnType e altri

Utility typeCosa faEsempio
ReturnType<F>il tipo di ritorno di un tipo funzioneReturnType<typeof createStore>
Parameters<F>i tipi dei parametri come tuplaParameters<typeof fetchPage>[0]
ConstructorParameters<C>i parametri del costruttore di una classe come tuplaConstructorParameters<typeof Point>
InstanceType<C>il tipo dell'istanza creata da un costruttoreInstanceType<typeof Point>
ThisParameterType<F>il tipo del parametro this di una funzioneThisParameterType<typeof greet>
OmitThisParameter<F>il tipo funzione senza il suo parametro thisil tipo di greet.bind(obj)
ThisType<T>imposta il tipo di this dentro i metodi di un oggetto letteralesi usa con noImplicitThis nelle API in stile builder
NoInfer<T>impedisce che un parametro di tipo venga dedotto da questa posizionefallback: NoInfer<C>

typeof createOrder serve perché queste utility ricevono un tipo, e createOrder è un valore. Lo stesso vale per le classi: typeof Point è il tipo del costruttore, mentre Point da solo, usato come tipo, indica già il tipo dell'istanza.

NoInfer controlla da dove un generic prende il suo tipo:

Senza NoInfer, TypeScript dedurrebbe C da entrambi gli argomenti e lo allargherebbe a "red" | "green" | "blue", quindi il refuso nel valore di ripiego verrebbe accettato.

Tipi per le stringhe: Uppercase, Lowercase, Capitalize, Uncapitalize

Utility typeCosa faEsempio
Uppercase<S>converte in maiuscolo un tipo letterale stringaUppercase<"get"> è "GET"
Lowercase<S>lo converte in minuscoloLowercase<"GET"> è "get"
Capitalize<S>mette in maiuscolo il primo carattereCapitalize<"name"> è "Name"
Uncapitalize<S>mette in minuscolo il primo carattereUncapitalize<"Name"> è "name"

Questi quattro sono integrati nel compilatore invece di essere scritti in TypeScript, e danno il meglio dentro i template literal types, come `on${Capitalize<E>}` per i nomi dei gestori di eventi.

Promise: Awaited

Utility typeCosa faEsempio
Awaited<T>il tipo che ottieni con await, scartando le promise annidateAwaited<Promise<Promise<number>>> è number

Awaited<ReturnType<typeof fn>> è il modo standard per dare un nome al tipo del risultato di una funzione async senza dichiararlo a parte.

Combinare gli utility types

Gli utility types si annidano. Alcune combinazioni ricorrono abbastanza spesso da valere la pena di impararle a memoria:

Un utility type annidato si legge dall'interno verso l'esterno: Readonly<Pick<Post, "id" | "title">> prima conserva due proprietà, poi le rende di sola lettura. Con gli stessi pezzi si costruisce un helper PartialBy che rende opzionali solo alcune chiavi; la pagina su Partial lo scrive per intero.

Gli utility types non fanno nulla a runtime

Ogni utility type viene cancellato quando il codice viene compilato. Un valore tipizzato come Omit<User, "password"> può ancora contenere una password a runtime, se l'oggetto da cui proviene ne aveva una:

Il tipo limita solo ciò che il tuo codice può leggere. Per togliere un campo dai dati, estrailo con una destrutturazione come nelle ultime righe, e per impedire modifiche a runtime usa Object.freeze, non Readonly. I tipi integrati sono mapped types e conditional types di una riga, quindi con gli stessi strumenti puoi scrivere i tuoi.

Domande frequenti

Cosa sono gli utility types in TypeScript?

Tipi generici forniti con TypeScript che trasformano altri tipi: Partial<T> rende opzionali tutte le proprietà, Pick<T, K> ne conserva alcune, ReturnType<F> ricava il tipo di ritorno di una funzione, e così via. Sono dichiarati nella libreria standard, quindi li usi senza importare nulla.

Devo importare gli utility types?

No. Partial, Omit, Record, ReturnType e gli altri sono tipi globali dei file di libreria integrati in TypeScript. Scrivi Partial<User> dove vuoi; non servono import né pacchetti npm.

Quali utility types sono integrati in TypeScript?

22, tutti dichiarati in lib.es5.d.ts: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ConstructorParameters, ReturnType, InstanceType, ThisParameterType, OmitThisParameter, ThisType, NoInfer, Awaited, Uppercase, Lowercase, Capitalize e Uncapitalize.

Gli utility types modificano gli oggetti a runtime?

No. Descrivono solo tipi e vengono cancellati dal JavaScript generato. Omit<User, "password"> non elimina nessuna proprietà password, e Readonly<T> non congela niente. Per cambiare l'oggetto reale devi scrivere il codice: una destrutturazione con rest, Object.freeze, e così via.

Posso scrivere i miei utility types?

Sì. Quelli integrati sono normale TypeScript: la maggior parte sono mapped types o conditional types di una riga in lib.es5.d.ts. type Nullable<T> = { [K in keyof T]: T[K] | null } è un utility type personalizzato scritto allo stesso modo.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA