La nueva sintaxis de parámetro de tipo const de TypeScript permite que una función mantenga intactos los tipos literales sin obligar a quienes la llaman a repartir as const por todas partes, reduciendo la fuente más común de errores de ensanchamiento de tipos (type-widening).

El problema del ensanchamiento que acecha al código genérico

Cuando una función genérica recibe un objeto literal, el compilador ensancha cualquier propiedad literal a su tipo primitivo más amplio.

function call<T>(arg: T) {}
call({ method: "GET" })   // T is inferred as { method: string }

El literal "GET" se colapsa a string. El código posterior que depende del valor exacto —como las uniones discriminadas o la extracción de template-literals— se rompe porque el tipo ya no conserva el literal preciso. Los desarrolladores han evitado esto durante mucho tiempo escribiendo { method: "GET" } as const en el lugar de la llamada, lo que le indica al compilador que mantenga el literal, pero esa solución recae en manos de quien llama a la función, no en la definición de la misma.

Parámetros de tipo const: una solución a nivel de firma

El nuevo modificador const en un parámetro de tipo le indica al compilador que infiera el tipo más estrecho posible para ese argumento genérico. Declarar una función como function foo<const T>(arg: T) hace que T se comporte automáticamente como si quien la llama hubiera escrito as const.

  • Los literales de string, number y boolean mantienen sus valores exactos ("GET" en lugar de string).
  • Los arrays se convierten en tuplas de solo lectura con cada elemento tipado con precisión.
  • Los objetos se transforman en estructuras profundamente de solo lectura, preservando los tipos literales en cada nivel de anidamiento.

Debido a que la restricción reside en la firma de la función, todos los que la llaman se benefician automáticamente; olvidar una conversión (cast) ya no es un camino hacia la falta de seguridad de tipos (unsoundness).

Por qué supera al clásico truco de as const

as const es una solución del lado del llamador. Requiere que cada consumidor de una función genérica recuerde añadir la aserción. Si se olvida una sola llamada, la seguridad de tipos se evapora. El parámetro de tipo const traslada la responsabilidad al propio diseño de la API: la función declara "necesito la forma más estrecha de lo que sea que pases", y el compilador lo hace cumplir.

Ese cambio es crucial para las librerías y utilidades que exponen constructores genéricos, fábricas de configuración o cualquier API donde el valor literal de un campo impulse la lógica de tipos. El autor de la librería puede garantizar una inferencia correcta sin tener que vigilar el código posterior.

Escenarios del mundo real que se benefician

  • Constructores de configuración – los nombres de entorno ("dev" | "prod") permanecen como literales, permitiendo comprobaciones de uniones discriminadas sin conversiones adicionales.
  • Definiciones de rutas de API – las cadenas de ruta se mantienen exactas, permitiendo que los tipos de template-literals extraigan parámetros ("/users/:id"\/users/${string}``).
  • Ayudantes de máquinas de estado – los identificadores de estado permanecen como literales fijos mediante el encadenamiento de métodos, evitando desajustes de estado accidentales.

En cada caso, el parámetro const elimina el código repetitivo (boilerplate) recurrente de as const y reduce la posibilidad de que se filtren errores sutiles.

Combinación con el operador satisfies

El operador satisfies valida que un valor se ajuste a un tipo estructural mientras preserva su información literal original. Usar ambos juntos ofrece lo mejor de ambos mundos: los parámetros const proporcionan una inferencia estrecha y satisfies asegura que el valor cumpla con la forma requerida.

function makeConfig<const C>(cfg: C) {
  // cfg is inferred with exact literals
}
const cfg = {
  env: "staging",
  ports: [8080, 8443],
} satisfies { env: string; ports: number[] };
makeConfig(cfg); // works, literals stay intact

Cuándo mantener as const

El parámetro const brilla cuando controlas la firma de la función. Si trabajas con funciones de terceros que carecen del modificador, o si necesitas preservar un literal de forma puntual para una variable local, as const sigue siendo la herramienta adecuada. Sigue siendo la forma predilecta de congelar un valor sin alterar la API llamada.

Qué esperar a continuación

La funcionalidad es reciente, por lo que las herramientas y los patrones de la comunidad están evolucionando. Espera actualizaciones en el soporte de los IDE que muestren la nueva sintaxis en el autocompletado y en las sugerencias de corrección rápida. Mantente atento a los mantenedores de librerías: muchos comenzarán a migrar los genéricos públicos a parámetros const, lo que podría introducir cambios disruptivos (breaking changes) en el código que antes dependía de conversiones explícitas con as const.

Conclusión: Al integrar la preservación de literales directamente en los parámetros de tipo de una función, los parámetros de tipo const de TypeScript eliminan una fuente común de errores de ensanchamiento y trasladan la seguridad del llamador de vuelta al diseñador de la API. Úsalos para cualquier punto de entrada genérico que controles; reserva as const para valores locales o APIs externas.