valueof en TypeScript: cómo obtener el tipo de valor de un objeto

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Existe un `valueof` similar a `keyof` en TypeScript? Optimización y rendimiento

\n\n

¿Alguna vez has escrito en TypeScript y te has sorprendido pensando: «Tengo keyof para las claves, ¿y dónde está valueof para los valores?» Si es así, no estás solo. Esta pregunta en Stack Overflow ha acumulado miles de visitas, y hoy la analizaremos de principio a fin. Pero no solo como teoría abstracta, sino con un enfoque en la optimización y el rendimiento de tu código. ¡Vamos allá!

\n\n

¿Por qué existe `keyof` y no `valueof`?

\n\n

En TypeScript existe el tipo utilitario incorporado keyof. Toma un tipo de objeto y devuelve la unión de todas sus claves:

\n\n
type Person = {\n  name: string;\n  age: number;\n  isActive: boolean;\n};\n\ntype PersonKeys = keyof Person; // "name" | "age" | "isActive"
\n\n

¿Y qué pasa con los valores? Queremos obtener string | number | boolean del mismo tipo. En la biblioteca estándar de TypeScript no existe tal cosa. ¿Por qué? Porque valueof no es simplemente una «operación inversa». Un objeto puede tener muchas claves con los mismos tipos, y necesitamos decidir cómo unirlos. ¡Pero eso no significa que no podamos escribir nuestro propio valueof!

\n\n

Creando nuestro propio `ValueOf`

\n\n

La forma más sencilla es usar el tipo de acceso por índice (indexed access type) en combinación con keyof:

\n\n
type ValueOf<T> = T[keyof T];\n\ntype PersonValues = ValueOf<Person>; // string | number | boolean
\n\n

¡Eso es todo! Acabamos de crear el tipo genérico ValueOf que funciona como valueof. Pero profundicemos más: ¿cómo afecta esto al rendimiento y cómo usarlo con inteligencia?

\n\n

Optimización: cuando `ValueOf` evita la duplicación

\n\n

Imagina que tienes un objeto de configuración con decenas de campos. Quieres escribir una función que acepte cualquier valor de ese objeto. Sin ValueOf, tendrías que enumerar los tipos manualmente:

\n\n
type Config = {\n  apiUrl: string;\n  timeout: number;\n  retries: number;\n  debug: boolean;\n};\n\n// Mal: duplicación de tipos\nfunction setConfigValue(key: string, value: string | number | boolean) {\n  // ...\n}
\n\n

Y ahora con ValueOf:

\n\n
// Bien: captura automáticamente todos los tipos de valores\nfunction setConfigValue(key: keyof Config, value: ValueOf<Config>) {\n  // TypeScript sabe que value solo puede ser string | number | boolean\n}
\n\n

Esto no solo reduce el código, sino que lo hace autodocumentado. Si agregas un nuevo campo a Config, TypeScript capturará automáticamente el nuevo tipo. Menos errores, más productividad en el desarrollo.

\n\n

`ValueOf` avanzado con tipos condicionales

\n\n

A veces es necesario obtener los valores solo de ciertas claves. Por ejemplo, todos los valores numéricos. Aquí es donde los tipos condicionales (conditional types) vienen al rescate:

\n\n
type 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\n

Este truco es especialmente útil cuando se trabaja con tipos grandes: puedes filtrar solo los valores necesarios y evitar comprobaciones innecesarias en tiempo de ejecución. La optimización a nivel de tipos es rendimiento gratuito, porque los tipos desaparecen en la compilación.

\n\n

Rendimiento en tiempo de ejecución: ¿es necesario?

\n\n

Un punto importante: ValueOf es una construcción puramente de tipos. No genera ningún código JavaScript. Pero su uso correcto puede aumentar indirectamente el rendimiento de tu aplicación:

\n\n
    \n
  • Menos errores — menos tiempo de depuración.
  • \n
  • Tipado más estricto — el compilador detecta
  • \n

Blogs

Book Recommendations