0Pricing
TypeScript Academy · Lección

El problema de HKT en TypeScript

Comprenda por qué los constructores de tipos genéricos son difíciles.

El problema de HKT en TypeScript es una lección gratuita de TypeScript Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de TypeScript Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de TypeScript Academy incluye 4 lecciones en total.

Qué es un tipo de tipo superior

Un tipo de tipo superior (HKT) abstrae no sobre un tipo concreto, sino sobre un constructor de tipos: algo como Array o Promise que necesita un argumento para convertirse en un tipo real.

Array por sí solo no es un tipo. Array<string> sí lo es. Array es una función sobre tipos, y los HKT permiten crear genéricos sobre ese tipo de funciones.

type StringArray = Array<string>;
type NumberArray = Array<number>;
// Array by itself is a type constructor, not a type

Los kinds, brevemente

Al igual que los valores tienen tipos, los constructores de tipos tienen kinds. Un tipo simple como number tiene el kind *. Array tiene el kind * -> *: se le proporciona un tipo y devuelve otro. Crear genéricos sobre estos constructores es lo que significa «de tipo superior».

type ValueLike = number;        // kind *
// Array needs one argument:    kind * -> *
// Map needs two arguments:     kind * -> * -> *

El objetivo: Functor<F>

En los lenguajes compatibles con HKT, puede escribir una única abstracción Functor<F> con un solo map que funcione con cualquier contenedor F, ya sea un array, una opción o una promesa. Una interfaz, muchos contenedores.

interface Wish_Functor<F> {
  map<A, B>(fa: F<A>, f: (a: A) => B): F<B>;
}
// F<A> here is the wish - and TypeScript rejects it

El problema

TypeScript no permite aplicar un parámetro de tipo a un argumento. No puede escribir F<A> cuando F es un parámetro genérico. El compilador muestra el error «Type F is not generic».

// interface Functor<F> {
//   map<A, B>(fa: F<A>, f: (a: A) => B): F<B>;
// }
// Error: Type F is not generic

Por qué TypeScript no los admite

Los parámetros de tipo de TypeScript son de primer orden: abarcan tipos concretos, no constructores de tipos. No existe una sintaxis para expresar que «F es algo que recibe un argumento de tipo». Por eso F<A> no tiene sentido para el compilador.

// You can pass number, string, User as F...
// but not Array, not Promise (the constructors themselves)

Un problema concreto

Sin HKT, debe duplicar map para cada contenedor: uno para arrays, otro para opciones y otro para promesas. La lógica es idéntica, pero el sistema de tipos no puede unificarlos.

declare function mapArray<A, B>(fa: A[], f: (a: A) => B): B[];
declare function mapOption<A, B>(fa: A | null, f: (a: A) => B): B | null;
// Same shape, but no way to abstract over the container

Qué queremos expresar

Queremos una sola firma: dada una contenedor de A y una función A -> B, devolver un contenedor de B y conservar el tipo de contenedor. Un array sigue siendo un array; una opción sigue siendo una opción.

// Wish: map<F, A, B>(fa: F<A>, f: (a: A) => B): F<B>
// where F is preserved across the call

Otros lenguajes

Haskell y Scala tienen HKT de forma nativa, por eso allí se pueden expresar clases de tipos como Functor, Applicative y Monad. TypeScript necesita una solución alternativa para aproximarse a la misma potencia.

// Haskell: class Functor f where fmap :: (a -> b) -> f a -> f b
// TypeScript: needs an encoding trick (next lessons)

La idea de la codificación

La solución alternativa habitual es la defuncionalización: en lugar de aplicar F directamente, asignamos a cada contenedor una etiqueta de cadena (una URI) y mantenemos un registro que asigna la etiqueta más un argumento al tipo concreto. La aplicación de tipos se convierte en una búsqueda.

// Instead of F<A>, we write Kind<F, A> where F is a URI string
// and a registry resolves it to the real type

Qué construirá

En las próximas lecciones construirá paso a paso la codificación de HKT al estilo de fp-ts: un registro URItoKind, una búsqueda mediante Kind y, finalmente, un Functor genérico cuyo map funciona con cualquier contenedor registrado.

// Roadmap:
// 1. Type constructors via URI strings
// 2. Kind<F, A> resolution
// 3. Generic Functor + instances

Por qué vale la pena conocerlo

Rara vez escribirá esta codificación por su cuenta, pero bibliotecas como fp-ts y Effect dependen de ella. Comprender este truco le permite leer sus tipos, escribir abstracciones genéricas sobre contenedores y apreciar lo que el sistema de tipos puede y no puede hacer.

// Recognizing Kind<F, A> in library code is the payoff

Comprobación rápida

Compruebe su comprensión del problema de los HKT.

Repaso

Ha conocido el problema de los tipos de tipo superior.

  • Los HKT abstraen sobre constructores de tipos como Array, no sobre tipos concretos.
  • Los parámetros de TypeScript son de primer orden, por lo que F<A> no es válido.
  • Esto impide crear un único Functor genérico con un solo map.
  • La solución es una codificación que utiliza etiquetas URI y un registro.

A continuación: definir constructores de tipos mediante cadenas URI.

Preguntas frecuentes

¿La lección «El problema de HKT en TypeScript» es gratis?

Sí — el texto completo de «El problema de HKT en TypeScript» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de TypeScript Academy, actualiza a CoddyKit PRO. El curso de TypeScript Academy incluye 4 lecciones en total.

¿Qué aprenderé en «El problema de HKT en TypeScript»?

Comprenda por qué los constructores de tipos genéricos son difíciles. Practicas TypeScript Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar TypeScript Academy?

No se requiere experiencia previa. TypeScript Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «El problema de HKT en TypeScript»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de TypeScript Academy?

Sí. Cada lección de TypeScript Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. El problema de HKT en TypeScript
  2. Definición de constructores de tipos
  3. El patrón HKT ligero
  4. Functors y mappers genéricos
← Volver a TypeScript Academy