Lors de la transformation de tableaux avec map, il est courant de n’avoir besoin que de propriétés spécifiques plutôt que de l’objet entier. L’écriture en ligne peut être verbeuse, mais définir une fonction d’extraction de propriétés à l’avance permet des expressions concises comme map(propsExtractor('id', 'name')).
Code
type LiteralObject = Record<string, unknown>
/** * Générer une fonction qui extrait uniquement les propriétés spécifiées d'un objet */export function propsExtractor< Props extends LiteralObject, PropKey extends keyof Props,>( ...props: PropKey[]): (obj: Props) => Pick<Props, PropKey> { return (obj: Props) => { const result: Partial<Props> = {} for (const prop of props) { if (Object.hasOwn(obj, prop)) { result[prop] = obj[prop] } } return result as Pick<Props, PropKey> }}Utilisation
type User = { id: string name: string email: string role: string createdAt: Date}
const users: User[] = [ { id: '1', name: 'Alice', email: 'alice@example.com', role: 'admin', createdAt: new Date() }, { id: '2', name: 'Bob', email: 'bob@example.com', role: 'user', createdAt: new Date() },]
// Extraire uniquement l'ID et le nomconst userSummaries = users.map(propsExtractor('id', 'name'))// => [{ id: '1', name: 'Alice' }, { id: '2', name: 'Bob' }]
// Fonctionne proprement même dans les maps imbriquéesconst departments = [ { name: 'Engineering', members: users }, { name: 'Sales', members: users },]
const summaries = departments.map(dept => ({ department: dept.name, members: dept.members.map(propsExtractor('id', 'name'))}))Fonctionnement
propsExtractoraccepte les noms de propriétés à extraire comme arguments variadiques- Renvoie une fonction de type
(obj: Props) => Pick<Props, PropKey>comme fermeture - La fonction renvoyée vérifie l’existence de la propriété avec
Object.hasOwnavant extraction - Le type utilitaire
Pickde TypeScript garantit une inférence de type précise pour la valeur de retour
L’utilisation de Object.hasOwn garantit la sécurité en évitant d’extraire par erreur des propriétés de la chaîne de prototypes.
Avantages
- Lisible : L’intention est claire avec des expressions comme
map(propsExtractor('id', 'name')) - Type-safe : L’inférence de type TypeScript détermine avec précision le type extrait
- Réutilisable : Définir une fois, utiliser à plusieurs endroits
- Gère bien l’imbrication : Maintient la lisibilité même avec plusieurs applications
mapBy
Précautions
Les propriétés qui n’existent pas ne sont pas incluses dans le résultat (pas même comme undefined). Si vous voulez inclure toutes les propriétés, supprimez la vérification Object.hasOwn. De plus, si vous extrayez de nombreuses propriétés, définir explicitement une interface peut être plus maintenable.
Applications
- Extraire uniquement les champs nécessaires des réponses API avant de les renvoyer aux clients
- Exclure les propriétés contenant des informations sensibles lors de la journalisation (créer une version de filtre inverse)
- Extraire un état partiel dans les sélecteurs Redux ou Zustand
- Implémenter une logique de récupération partielle similaire à la sélection de champs GraphQL
hsb.horse