Pick et Omit : Manipuler les interfaces en choisissant ou excluant des propriétés
Après Record, Exclude, Extract et NonNullable, place à deux utilitaires essentiels pour créer des types dérivés à partir de vos interfaces existantes.
Publié le 1er mars 2026 • Temps de lecture : 7 min
Introduction : Pourquoi dériver des types ?
Dans notre précédent article sur les utilitaires avancés, nous avons vu comment manipuler des unions et créer des dictionnaires typés. Aujourd'hui, nous allons nous concentrer sur un besoin très fréquent : créer une version allégée ou modifiée d'une interface existante.
Imaginez que vous ayez une interface Utilisateur avec 10 propriétés. Dans une fonction d'affichage de profil, vous n'avez besoin que de 5 d'entre elles. Dans un formulaire de mise à jour, vous voulez rendre certaines propriétés optionnelles. Dans une réponse API, vous voulez exclure des données sensibles comme le mot de passe.
Pick et Omit sont vos meilleurs alliés pour ces situations. Ils permettent de créer de nouveaux types à partir d'un type existant, sans duplication de code.
Prérequis
Cet article est la suite directe de notre article sur les utilitaires avancés. Si vous n'êtes pas familier avec les génériques et les interfaces, je vous recommande de commencer par le début de la série.
1. Pick<Type, Clés> : Sélectionner des propriétés
Pick construit un nouveau type en sélectionnant un ensemble de propriétés (Clés) à partir d'un type existant (Type).
Syntaxe
Exemple simple
id: number;
nom: string;
email: string;
motDePasse: string;
dateInscription: Date;
estActif: boolean;
}
// Pour afficher un profil public, on ne veut que certaines infos
type ProfilPublic = Pick<Utilisateur, "nom" | "dateInscription" | "estActif">;
const profil: ProfilPublic = {
nom: "Jean Dupont",
dateInscription: new Date("2025-01-15"),
estActif: true
}; // ✅ Valide, on a exactement les propriétés sélectionnées
Cas d'usage concret : Composant d'affichage
id: string;
nom: string;
description: string;
prix: number;
stock: number;
codeBarre: string;
fournisseurId: string;
}
// Dans une carte produit, on n'affiche que l'essentiel
type CarteProduit = Pick<Produit, "nom" | "prix" | "stock">;
function AfficherCarteProduit(produit: CarteProduit) {
return (
<div className="carte-produit">
<h3>{produit.nom}</h3>
<p>Prix: {produit.prix}€</p>
<p>Stock: {produit.stock} unités</p>
</div>
);
}
// ✅ On ne peut pas accidentellement utiliser id ou fournisseurId ici
Pick avec des unions de chaînes littérales
type DonnéesSensibles = Pick<Utilisateur, ClésSensibles>; // { motDePasse: string } (si ces clés existent)
🎯 À retenir sur Pick
Pick est idéal quand vous voulez extraire un sous-ensemble cohérent d'un type plus grand. Il garantit que vous n'utilisez que les propriétés nécessaires dans un contexte donné.
2. Omit<T, K> : Exclure des propriétés
Omit fait l'inverse de Pick : il construit un nouveau type en excluant un ensemble de propriétés (K) à partir du type original (T).
Syntaxe
Exemple simple
id: number;
nom: string;
email: string;
motDePasse: string;
dateInscription: Date;
estActif: boolean;
}
// Pour renvoyer des données utilisateur au frontend, on exclut le mot de passe
type UtilisateurSansMotDePasse = Omit<Utilisateur, "motDePasse">;
const utilisateurFrontend: UtilisateurSansMotDePasse = {
id: 1,
nom: "Jean Dupont",
email: "jean@example.com",
dateInscription: new Date("2025-01-15"),
estActif: true
}; // ✅ Plus de propriété motDePasse !
Cas d'usage concret : Création d'objet sans ID
Quand vous créez un nouvel utilisateur, l'ID est généralement généré par la base de données. Vous voulez donc un type pour les données d'entrée, sans l'ID.
id: number;
nom: string;
email: string;
motDePasse: string;
}
// Type pour la création (sans l'ID auto-généré)
type UtilisateurCréation = Omit<Utilisateur, "id">;
async function créerUtilisateur(données: UtilisateurCréation): Promise<Utilisateur> {
// Ici, la BDD générera l'ID
const nouvelUtilisateur = {
...données,
id: generateId() // généré par la BDD
};
return nouvelUtilisateur;
}
// ✅ TypeScript nous empêche de passer un objet avec un id
// créerUtilisateur({ id: 123, nom: "Jean", email: "...", motDePasse: "..." }); // ❌ Erreur
Exclure plusieurs propriétés
type DocumentSansAudit = Omit<Document, DonnéesAudit>; // Exclut toutes les propriétés d'audit
💡 Omit est plus pratique quand vous avez beaucoup de propriétés à garder et seulement quelques-unes à exclure. Si vous avez 20 propriétés et que vous voulez en garder 18, Omit est bien plus lisible que Pick avec 18 clés.
3. Pick vs Omit : Quand utiliser l'un ou l'autre ?
| Situation | Solution recommandée | Explication |
|---|---|---|
| Je veux un sous-ensemble spécifique (ex: profil public avec 3 champs sur 10) | Pick | Vous listez explicitement ce que vous voulez, c'est clair et autodocumenté |
| Je veux exclure quelques propriétés sensibles (ex: mot de passe, token) | Omit | Plus concis et plus sûr (vous n'oublierez pas d'exclure une propriété) |
| L'interface source peut évoluer (ajout de propriétés) | Omit | Les nouvelles propriétés seront automatiquement incluses (sauf si vous les excluez explicitement) |
| Je veux un contrat strict qui ne doit pas changer | Pick | Le type est figé, l'ajout de propriétés dans la source n'affecte pas le type dérivé |
Règle empirique
type PetitSousEnsemble = Pick<GrosseInterface, "prop1" | "prop2">;
// Si le nombre de propriétés à exclure est inférieur au nombre de propriétés à garder → OMIT
type GrosseInterfaceSansQuelquesProps = Omit<GrosseInterface, "propSensible1" | "propSensible2">;
Cas pratiques : Combiner Pick, Omit et autres utilitaires
La vraie puissance apparaît quand on combine ces utilitaires entre eux ou avec d'autres.
Exemple 1 : Formulaire de mise à jour avec champs optionnels
id: number;
nom: string;
email: string;
motDePasse: string;
avatar: string;
}
// Pour la mise à jour, on ne permet de modifier que certaines infos
// et toutes ces modifications sont optionnelles
type MiseÀJourUtilisateur = Partial<Pick<Utilisateur, "nom" | "email" | "avatar">>;
function mettreÀJourProfil(id: number, modifications: MiseÀJourUtilisateur) {
// Toutes les propriétés sont optionnelles, on peut envoyer juste ce qui a changé
console.log("Mise à jour:", modifications);
}
mettreÀJourProfil(1, { nom: "Nouveau Nom" }); // ✅
mettreÀJourProfil(1, { email: "nouveau@email.com", avatar: "nouveau.jpg" }); // ✅
Exemple 2 : Réponse API avec métadonnées exclues
données: T;
status: number;
message: string;
timestamp: string;
versionAPI: string;
tempsExécution: number;
}
// Pour le client frontend, on exclut les métadonnées techniques
type RéponseClient<T> = Omit<RéponseAPI<T>, "timestamp" | "versionAPI" | "tempsExécution">;
function traiterRéponse<T>(réponse: RéponseClient<T>): T {
if (réponse.status >= 400) {
throw new Error(réponse.message);
}
return réponse.données;
}
Exemple 3 : Création d'un type conditionnel basé sur un rôle
interface Permissions {
peutSupprimer: boolean;
peutModifier: boolean;
peutVoir: boolean;
peutCréer: boolean;
peutGérerUtilisateurs: boolean;
}
type PermissionsParRôle = {
[R dans Rôle]: R extends "admin"
? Permissions // Admin a toutes les permissions
: R extends "modérateur"
? Pick<Permissions, "peutModifier" | "peutVoir"> // Modérateur peut modifier et voir
: Pick<Permissions, "peutVoir">; // Utilisateur peut seulement voir
};
const permissions: PermissionsParRôle = {
admin: { peutSupprimer: true, peutModifier: true, peutVoir: true, peutCréer: true, peutGérerUtilisateurs: true },
modérateur: { peutModifier: true, peutVoir: true },
utilisateur: { peutVoir: true }
};
🎯 Point clé
Pick et Omit sont vos outils de précision pour sculpter vos types. Ils vous permettent de suivre le principe DRY (Don't Repeat Yourself) même au niveau des types, en réutilisant des interfaces existantes plutôt que d'en recréer de nouvelles.
Conclusion : Des types précis pour des cas précis
Nous avons exploré deux utilitaires fondamentaux pour la manipulation d'interfaces :
- Pick : pour sélectionner exactement les propriétés dont vous avez besoin.
- Omit : pour exclure des propriétés indésirables.
Ces deux outils sont complémentaires et vous permettent de créer des types dérivés parfaitement adaptés à chaque contexte : affichage public, formulaires de création/mise à jour, réponses API, etc.
🚀 Prochaines étapes
Nous continuons notre exploration des utilitaires TypeScript. Voici ce qui nous attend :
- Partial, Required, Readonly : Rendre les propriétés optionnelles, obligatoires ou en lecture seule.
- Parameters, ReturnType : Extraire les types des paramètres et du retour d'une fonction.
- Awaited : Déballer le type d'une Promise.
- Les template literal types : Créer des types dynamiquement à partir de chaînes.
💡 Le mot de la fin
Pick et Omit sont vos meilleurs amis pour éviter la duplication de code. Chaque fois que vous avez envie de copier-coller une interface pour en modifier quelques propriétés, demandez-vous si Pick ou Omit ne pourrait pas faire le travail à votre place.
👋 Un mot de l'auteur
Merci d'avoir lu cet article jusqu'au bout ! J'espère que ces explications sur Pick et Omit vous seront utiles dans vos projets TypeScript.
Si vous avez aimé ce contenu, n'hésitez pas à le partager autour de vous ou à me laisser un commentaire. Votre soutien est ce qui me motive à continuer à produire des ressources de qualité.
📢 Prochain article : "Partial, Required, Readonly : Modifier les contraintes des propriétés." Restez connectés !
Questions Fréquentes
Peut-on utiliser Pick et Omit avec des classes ?
Oui, Pick et Omit fonctionnent avec tous les types, y compris les classes. Ils créeront un nouveau type basé sur la structure de la classe.
Que se passe-t-il si j'essaie de Pick une propriété qui n'existe pas ?
TypeScript lèvera une erreur. Pick est type-safe : vous ne pouvez sélectionner que des propriétés qui existent réellement dans le type source.
Et si j'utilise Omit sur une propriété qui n'existe pas ?
Dans ce cas, TypeScript ne dira rien (le type résultant sera identique à l'original). Omit ignore silencieusement les clés qui n'existent pas.
Pick et Omit fonctionnent-ils avec des types indexés (signatures d'index) ?
Oui, mais avec quelques nuances. Si vous avez une signature d'index comme [key: string]: number, Pick et Omit peuvent être utilisés, mais ils ne peuvent pas sélectionner/exclure des propriétés individuelles de cette signature.
Existe-t-il une version "profonde" de Pick et Omit pour les objets imbriqués ?
TypeScript ne fournit pas nativement de versions "deep" (récursives) de Pick et Omit, mais vous pouvez les créer vous-même avec des types conditionnels avancés ou utiliser des bibliothèques comme type-fest qui les proposent.