Existe-t-il un `valueof` similaire à `keyof` en TypeScript ? Optimisation et performance
\n\nAvez-vous déjà codé en TypeScript en vous demandant : « J'ai keyof pour les clés, mais où est le valueof pour les valeurs ? » Si oui, vous n'êtes pas seul. Cette question sur Stack Overflow cumule des milliers de vues, et aujourd'hui nous allons la décortiquer de A à Z. Mais pas comme une simple théorie abstraite : nous mettrons l'accent sur l'optimisation et la performance de votre code. C'est parti !
Pourquoi `keyof` existe-t-il et pas `valueof` ?
\n\nTypeScript propose un type utilitaire intégré keyof. Il prend un type d'objet et retourne l'union de toutes ses clés :
type Person = {\n name: string;\n age: number;\n isActive: boolean;\n};\n\ntype PersonKeys = keyof Person; // "name" | "age" | "isActive"\n\nEt pour les valeurs ? On aimerait obtenir string | number | boolean à partir du même type. Cela n'existe pas dans la bibliothèque standard de TypeScript. Pourquoi ? Parce que valueof n'est pas simplement une « opération inverse ». Un objet peut avoir plusieurs clés avec les mêmes types, et il faut décider comment les fusionner. Mais cela ne signifie pas que nous ne pouvons pas créer notre propre valueof !
Créer son propre `ValueOf`
\n\nLa méthode la plus simple consiste à utiliser un type d'accès indexé (indexed access type) combiné à keyof :
type ValueOf<T> = T[keyof T];\n\ntype PersonValues = ValueOf<Person>; // string | number | boolean\n\nEt voilà ! Nous venons de créer un type générique ValueOf qui fonctionne comme un valueof. Mais allons plus loin : voyons comment cela impacte la performance et comment l'utiliser intelligemment.
Optimisation : quand `ValueOf` évite la duplication
\n\nImaginez que vous ayez un objet de configuration avec des dizaines de champs. Vous voulez écrire une fonction qui accepte n'importe quelle valeur de cet objet. Sans ValueOf, vous devriez énumérer les types manuellement :
type Config = {\n apiUrl: string;\n timeout: number;\n retries: number;\n debug: boolean;\n};\n\n// Mauvais : duplication des types\nfunction setConfigValue(key: string, value: string | number | boolean) {\n // ...\n}\n\nEt maintenant avec ValueOf :
// Bon : récupère automatiquement tous les types de valeurs\nfunction setConfigValue(key: keyof Config, value: ValueOf<Config>) {\n // TypeScript sait que value ne peut être que string | number | boolean\n}\n\nCela réduit non seulement le code, mais le rend aussi auto-documenté. Si vous ajoutez un nouveau champ à Config, TypeScript intégrera automatiquement le nouveau type. Moins d'erreurs, plus de productivité.
`ValueOf` avancé avec les types conditionnels
\n\nParfois, vous avez besoin d'obtenir les valeurs uniquement de certaines clés. Par exemple, toutes les valeurs numériques. C'est là que les types conditionnels (conditional types) entrent en jeu :
\n\ntype NumericValues<T> = {\n [K in keyof T]: T[K] extends number ? T[K] : never;\n}[keyof T];\n\ntype ConfigNumeric = NumericValues<Config>; // number (timeout | retries)\n\nCette astuce est particulièrement utile avec des types volumineux : vous pouvez filtrer uniquement les valeurs nécessaires et éviter des vérifications superflues à l'exécution. L'optimisation au niveau des types, c'est de la performance gratuite, car les types disparaissent à la compilation.
\n\nPerformance à l'exécution : est-ce vraiment nécessaire ?
\n\nPoint important : ValueOf est une construction purement typée. Elle ne génère aucun code JavaScript. Mais une utilisation judicieuse peut indirectement améliorer les performances de votre application :
- \n
- Moins de bugs — moins de temps passé à déboguer. \n
- Typage plus strict — le compilateur détecte