Tipi di utilità in TypeScript
Questo articolo spiega i tipi di utilità in TypeScript.
YouTube Video
Tipi di utilità in TypeScript
I tipi di utilità di TypeScript sono strumenti pratici per creare nuovi tipi basati su tipi esistenti. Ciò consente definizioni di tipo più flessibili e aumenta la riutilizzabilità del codice. Qui spiegheremo in dettaglio i tipi di utilità più comunemente usati e discuteremo come utilizzare ciascuno con esempi di codice.
Partial<T>
Partial<T>
rende tutte le proprietà di un tipo oggetto opzionali (consentendo undefined
). È utile quando vuoi utilizzare solo alcune delle proprietà che il tipo originale possiede.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7function updateUser(user: Partial<User>) {
8 console.log(user);
9}
10
11updateUser({ name: "Alice" }); // Updates only 'name'
Spiegazione:
Nell'esempio sopra, l'uso di Partial<User>
rende tutte le proprietà del tipo User
opzionali. Pertanto, nella funzione updateUser
, puoi passare solo un sottoinsieme delle proprietà.
Required<T>
Required<T>
rende tutte le proprietà, incluse quelle opzionali, obbligatorie. Si usa quando vuoi convertire proprietà opzionali in obbligatorie.
1interface User {
2 id: number;
3 name?: string;
4 age?: number;
5}
6
7function createUser(user: Required<User>) {
8 console.log(user);
9}
10
11// createUser({ id: 1 }); // Error: 'name' and 'age' are required
12createUser({ id: 1, name: "Alice", age: 25 });
Spiegazione:
Usando Required<User>
, proprietà come name
e age
sono trattate come obbligatorie.
Readonly<T>
Readonly<T>
rende tutte le proprietà di un oggetto di sola lettura. Ciò impedisce che i valori dell'oggetto vengano modificati.
1interface User {
2 id: number;
3 name: string;
4}
5
6const user: Readonly<User> = {
7 id: 1,
8 name: "Alice"
9};
10
11// user.id = 2; // Error: 'id' is read-only
12console.log(user);
Spiegazione:
Usando Readonly<T>
, puoi proteggere le proprietà di un oggetto da modifiche. È efficace quando vuoi impedire che i dati vengano modificati accidentalmente durante lo sviluppo.
Record<K, T>
Record<K, T>
crea un tipo mappa con tipi di chiave e valore specificati. K
è il tipo per le chiavi (come string
o number
), e T
è il tipo per i valori.
1type Roles = "admin" | "user" | "guest";
2interface Permissions {
3 read: boolean;
4 write: boolean;
5}
6
7const rolePermissions: Record<Roles, Permissions> = {
8 admin: { read: true, write: true },
9 user: { read: true, write: false },
10 guest: { read: false, write: false },
11};
12
13console.log(rolePermissions);
Spiegazione:
Record<K, T>
è utile quando vuoi definire coppie chiave-valore. Nell'esempio sopra, i permessi sono definiti in base ai ruoli utente.
Pick<T, K>
Pick<T, K>
estrae solo le proprietà specificate da un tipo oggetto. Puoi creare un nuovo tipo estraendo solo le proprietà necessarie.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7type UserSummary = Pick<User, "id" | "name">;
8
9const summary: UserSummary = {
10 id: 1,
11 name: "Alice"
12};
13
14console.log(summary);
Spiegazione:
Usando Pick<T, K>
, puoi estrarre proprietà specifiche da un tipo oggetto e trattarle come un nuovo tipo. Ad esempio, solo id
e name
vengono estratti nell'esempio sopra.
Omit<T, K>
Omit<T, K>
esclude proprietà specificate da un tipo oggetto. Questa è l'operazione opposta a Pick
.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5 email: string;
6}
7
8type UserWithoutEmail = Omit<User, "email">;
9
10const userWithoutEmail: UserWithoutEmail = {
11 id: 1,
12 name: "Alice",
13 age: 25
14};
15
16console.log(userWithoutEmail);
Spiegazione:
Usando Omit<T, K>
, è possibile creare un nuovo tipo escludendo proprietà specificate. Nell'esempio sopra, la proprietà email
viene esclusa.
Exclude<T, U>
Exclude<T, U>
crea un nuovo tipo rimuovendo il tipo U
dal tipo unione T
. Viene utilizzato quando si desidera rimuovere un tipo specifico.
1type Status = "active" | "inactive" | "pending";
2type ExcludedStatus = Exclude<Status, "pending">;
3
4const status: ExcludedStatus = "active"; // "pending" is excluded, so it cannot be chosen
5console.log(status);
Spiegazione:
Usando Exclude<T, U>
, è possibile rimuovere tipi non necessari da un tipo unione. Nell'esempio sopra, poiché "pending"
viene escluso, possono essere selezionati solo "active"
o "inactive"
.
Extract<T, U>
Extract<T, U>
estrae le porzioni che corrispondono al tipo U
all'interno del tipo unione T
. È utile quando si desidera estrarre solo un tipo specifico.
1type Status = "active" | "inactive" | "pending";
2type ActiveStatus = Extract<Status, "active" | "pending">;
3
4const status: ActiveStatus = "active"; // "inactive" cannot be chosen
5console.log(status);
Spiegazione:
Extract<T, U>
esegue l'operazione opposta a Exclude
. Nell'esempio sopra, possono essere selezionati solo "active"
e "pending"
.
NonNullable<T>
NonNullable<T>
crea un tipo con null
e undefined
esclusi. È utile quando si desidera escludere questi valori dai tipi opzionali.
1type UserName = string | null | undefined;
2type ValidUserName = NonNullable<UserName>;
3
4const name: ValidUserName = "Alice"; // null and undefined cannot be chosen
5console.log(name);
Spiegazione:
NonNullable<T>
esclude null
e undefined
da un tipo che li contiene. Questo è utile quando si vuole garantire che un valore esista sicuramente.
Conclusione
I tipi di utilità di TypeScript sono strumenti potenti per rendere le definizioni di tipo più concise e flessibili. Capire e utilizzare adeguatamente tipi di utilità di base come Partial
, Required
, Readonly
, Record
, ecc., può migliorare la riutilizzabilità e la manutenibilità del codice. Padroneggiare questi tipi consente di creare definizioni di tipo più robuste e sicure, favorendo uno sviluppo efficiente.
L'operatore keyof
di TypeScript
L'operatore keyof
di TypeScript viene utilizzato per ottenere tutti i nomi delle proprietà di un tipo oggetto. Utilizzando questo operatore, è possibile ottenere le chiavi di un tipo oggetto come tipo unione. Questo è estremamente utile per scrivere codice sicuro per i tipi.
Uso di base
1interface Person {
2 name: string;
3 age: number;
4 email: string;
5}
6
7// Use keyof to get the property names of Person
8type PersonKeys = keyof Person; // "name" | "age" | "email"
Esempio di utilizzo
-
Utilizzo negli Argomenti delle Funzioni
È possibile utilizzare
keyof
per definire una funzione con tipi basati su proprietà specifiche di un oggetto.
1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2 return obj[key];
3}
4
5const person: Person = { name: "Alice", age: 30, email: "alice@example.com" };
6const name = getProperty(person, "name"); // type is string
7const age = getProperty(person, "age"); // type is number
-
Miglioramento dei Vincoli di Tipo
Utilizzando
keyof
, è possibile garantire che le chiavi passate a una funzione vengano validate durante la fase di compilazione.
1// Passing an invalid property name results in an error
2const invalid = getProperty(person, "invalidKey"); // Error
Riepilogo
- L'operatore
keyof
viene utilizzato per recuperare tutti i nomi delle proprietà di un tipo oggetto. - È possibile ottenere i nomi delle proprietà come tipo unione, ottenendo codice sicuro per i tipi.
- Utilizzandolo negli argomenti di funzione, è possibile limitare la funzione ad accettare solo nomi di proprietà validi.
In questo modo, l'operatore keyof
migliora la sicurezza dei tipi in TypeScript e ti aiuta a scrivere codice più robusto.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.