Tirer Parti des Types Utilitaires en TypeScript

Disponible en :

TypeScript offre de nombreux types utilitaires qui te permettent de manipuler les types de manière dynamique et pratique. Que ce soit pour rendre des propriétés facultatives, immuables ou pour filtrer certains champs d'un type, ces utilitaires peuvent t’aider à écrire un code plus propre, plus sûr, et plus lisible.

Dans cet article, tu découvriras certains des types utilitaires les plus couramment utilisés en TypeScript, avec des exemples concrets pour te montrer comment et quand les utiliser.

1. Partial<T>

Le type utilitaire Partial<T> transforme toutes les propriétés d’un type T en propriétés optionnelles. Cela est particulièrement utile quand tu travailles avec des objets où toutes les propriétés ne sont pas toujours nécessaires.

Exemple

Imaginons un type User avec des propriétés obligatoires :

typescript
1type User = {
2 id: number;
3 name: string;
4 email: string;
5};

Si tu souhaites créer une fonction qui met à jour un utilisateur, mais qui n’a besoin que d’un sous-ensemble de ces propriétés, tu peux utiliser Partial<User> :

typescript
1function updateUser(user: User, updates: Partial<User>) {
2 return { ...user, ...updates };
3}
4
5// Utilisation
6const user: User = { id: 1, name: 'Alice', email: 'alice@example.com' };
7const updatedUser = updateUser(user, { name: 'Alicia' });

Grâce à Partial<User>, tu peux maintenant mettre à jour seulement certaines propriétés sans devoir fournir toutes les autres.

2. Readonly<T>

Readonly<T> rend toutes les propriétés d’un type T immuables. Cela signifie qu’une fois que l’objet est créé, tu ne peux plus modifier ses propriétés, ce qui est idéal pour les objets constants.

Exemple

typescript
1type Config = {
2 apiEndpoint: string;
3 timeout: number;
4};
5
6const config: Readonly<Config> = {
7 apiEndpoint: 'https://api.example.com',
8 timeout: 5000,
9};
10
11// Erreur : Impossible d'assigner à 'timeout' car c'est une propriété en lecture seule
12config.timeout = 3000;

En utilisant Readonly<Config>, tu t’assures que config reste immuable tout au long de l’exécution.

3. Pick<T, K>

Le type utilitaire Pick<T, K> crée un nouveau type en sélectionnant seulement certaines propriétés d’un type T. Cela est utile quand tu souhaites créer une sous-partie d’un type existant.

Exemple

typescript
1type User = {
2 id: number;
3 name: string;
4 email: string;
5 address: string;
6};
7
8type UserSummary = Pick<User, 'id' | 'name'>;
9
10const userSummary: UserSummary = {
11 id: 1,
12 name: 'Alice',
13};
14
15// Erreur : La propriété 'email' n'existe pas sur le type 'UserSummary'
16userSummary.email = 'alice@example.com';

Avec Pick<User, "id" | "name">, tu crées un type UserSummary qui contient seulement les propriétés id et name.

4. Omit<T, K>

Inversement, Omit<T, K> crée un nouveau type en excluant certaines propriétés d’un type T. C’est l’inverse de Pick.

Exemple

typescript
1type UserWithoutAddress = Omit<User, 'address'>;
2
3const userWithoutAddress: UserWithoutAddress = {
4 id: 1,
5 name: 'Alice',
6 email: 'alice@example.com',
7};
8
9// Erreur : La propriété 'address' n'existe pas sur le type 'UserWithoutAddress'
10userWithoutAddress.address = '123 Main St';

Dans cet exemple, UserWithoutAddress contient toutes les propriétés de User, sauf address.

5. Record<K, T>

Record<K, T> est utilisé pour créer un type d’objet où les clés K sont d’un type spécifique, et les valeurs sont du type T. Cela est utile pour créer des objets associatifs, comme des dictionnaires ou des mappages.

Exemple

Supposons que tu veuilles créer un objet associant des rôles d’utilisateur à des droits d’accès :

typescript
1type Role = 'admin' | 'user' | 'guest';
2type Permissions = 'read' | 'write' | 'delete';
3
4const rolePermissions: Record<Role, Permissions[]> = {
5 admin: ['read', 'write', 'delete'],
6 user: ['read', 'write'],
7 guest: ['read'],
8};

Dans cet exemple, Record<Role, Permissions[]> assure que l’objet rolePermissions contient toutes les clés admin, user, et guest, avec des valeurs de type Permissions[].

6. Exclude<T, U>

Exclude<T, U> permet de créer un type en excluant certains types d’un autre type. C’est utile pour filtrer des types spécifiques à partir d’un Union Type.

Exemple

typescript
1type Status = 'active' | 'inactive' | 'suspended';
2
3type ActiveStatus = Exclude<Status, 'suspended'>;
4
5const status: ActiveStatus = 'active'; // Valide
6const anotherStatus: ActiveStatus = 'suspended'; // Erreur

En utilisant Exclude<Status, "suspended">, tu crées un type ActiveStatus qui ne peut pas être "suspended".

Conclusion

Les types utilitaires de TypeScript te permettent d’exprimer des types complexes de manière concise et lisible. En exploitant Partial, Readonly, Pick, Omit, Record, et Exclude, tu peux manipuler tes types de façon dynamique et répondre aux besoins de ton application sans alourdir ton code.

Ces utilitaires ne sont que la pointe de l’iceberg : TypeScript offre bien d’autres types utilitaires avancés. Prends le temps d’explorer ces outils, et ton code sera plus maintenable, plus sûr et plus facile à lire.


En appliquant ces astuces, tu pourras manipuler tes types de manière plus efficace et écrire du code TypeScript encore plus robuste. Bon codage !

Partagez cet article


Sébastien Timoner

Sébastien TIMONER

Lead Développeur
Expert en Développement sur Mesure
Aix-en-Provence, France

Expert en développement web et gestion d’équipes techniques, je me spécialise dans la création et l’optimisation de solutions numériques performantes. Grâce à une maîtrise approfondie de technologies modernes comme React.js, Node.js, TypeScript, Symfony et Zephyr OS pour l'IoT, j’assure la réussite de projets SaaS et IoT complexes, de la conception à la mise en production, pour des entreprises de divers secteurs, au sein d'offroadLabs.

Chez offroadLabs, je propose des services de développement sur mesure, alliant expertise technique et approche collaborative. Que ce soit pour créer une solution SaaS innovante, développer des systèmes IoT avec Zephyr OS, moderniser une application existante, ou accompagner la montée en compétences d’une équipe, je m’engage à fournir des solutions robustes et performantes, adaptées aux besoins spécifiques de chaque projet.

Je suis disponible pour des missions autour d’Aix-en-Provence ou en full remote.

Tirer Parti des Types Utilitaires en TypeScript