O Problema de HKT no TypeScript
Entenda por que construtores de tipos genéricos são difíceis.
O Problema de HKT no TypeScript é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 4 aulas no total.
O que é um tipo de ordem superior
Um tipo de ordem superior (HKT) abstrai não um tipo concreto, mas um construtor de tipos: algo como Array ou Promise que precisa de um argumento para se tornar um tipo real.
Array sozinho não é um tipo. Array<string> é. Array é uma função sobre tipos, e os HKT permitem criar generalizações sobre essas funções.
type StringArray = Array<string>;
type NumberArray = Array<number>;
// Array by itself is a type constructor, not a typeTipos e categorias, brevemente
Assim como os valores têm tipos, os construtores de tipos têm categorias. Um tipo simples como number tem a categoria *. Array tem a categoria * -> *: forneça um tipo e obtenha outro tipo. Criar generalizações sobre eles é o que significa ser de "ordem superior".
type ValueLike = number; // kind *
// Array needs one argument: kind * -> *
// Map needs two arguments: kind * -> * -> *O objetivo: Functor<F>
Em linguagens com suporte a HKT, você pode escrever uma única abstração Functor<F> com um único map que funciona para qualquer contêiner F, seja ele um vetor, uma opção ou uma promessa. Uma interface, muitos contêineres.
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 itO problema
O TypeScript não oferece suporte à aplicação de um parâmetro de tipo a um argumento. Você não pode escrever F<A> quando F é um parâmetro genérico. O compilador informa o erro "O tipo F não é genérico".
// interface Functor<F> {
// map<A, B>(fa: F<A>, f: (a: A) => B): F<B>;
// }
// Error: Type F is not genericPor que TS não oferece isso
Os parâmetros de tipo do TypeScript são de primeira ordem: eles abrangem tipos concretos, não construtores de tipos. Não há sintaxe para dizer que "F é algo que recebe um argumento de tipo". Portanto, F<A> não faz sentido para o compilador.
// You can pass number, string, User as F...
// but not Array, not Promise (the constructors themselves)Uma Dificuldade Concreta
Sem HKT, você precisa duplicar map para cada contêiner: um para vetores, um para opções e um para promessas. A lógica é idêntica, mas o sistema de tipos não consegue unificá-los.
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 containerO Que Queremos Expressar
Queremos uma única assinatura: dada uma contêiner de A e uma função A -> B, retornar um contêiner de B, preservando o tipo do contêiner. O vetor continua sendo um vetor; a opção continua sendo uma opção.
// Wish: map<F, A, B>(fa: F<A>, f: (a: A) => B): F<B>
// where F is preserved across the callOutras Linguagens
Haskell e Scala têm suporte nativo a HKT, por isso classes de tipos como Functor, Applicative e Monad podem ser expressas nelas. O TypeScript precisa de uma solução alternativa para aproximar esse mesmo poder.
// Haskell: class Functor f where fmap :: (a -> b) -> f a -> f b
// TypeScript: needs an encoding trick (next lessons)A Ideia da Codificação
A solução alternativa padrão é a defuncionalização: em vez de aplicar F diretamente, damos a cada contêiner um rótulo de cadeia de caracteres (uma URI) e mantemos um registro que mapeia o rótulo e um argumento para o tipo concreto. A aplicação de tipos se torna uma consulta.
// Instead of F<A>, we write Kind<F, A> where F is a URI string
// and a registry resolves it to the real typeO Que Você Vai Construir
Nas próximas lições, você construirá passo a passo a codificação de HKT no estilo do fp-ts: um registro URItoKind, uma consulta Kind e, por fim, um Functor genérico cujo map funciona para qualquer contêiner registrado.
// Roadmap:
// 1. Type constructors via URI strings
// 2. Kind<F, A> resolution
// 3. Generic Functor + instancesPor Que Vale a Pena Conhecer
Você raramente escreverá essa codificação por conta própria, mas bibliotecas como fp-ts e Effect dependem dela. Entender esse truque permite ler os tipos dessas bibliotecas, escrever abstrações genéricas sobre contêineres e compreender melhor o que o sistema de tipos pode ou não fazer.
// Recognizing Kind<F, A> in library code is the payoffVerificação Rápida
Teste sua compreensão do problema de HKT.
Recapitulação
Você conheceu o problema dos tipos de ordem superior.
- Os tipos HKT abstraem construtores de tipos como
Array, não tipos concretos. - Os parâmetros do TypeScript são de primeira ordem, portanto
F<A>é ilegal. - Isso impede um único
Functorgenérico com um únicomap. - A solução é uma codificação usando rótulos URI e um registro.
Próximo: definir construtores de tipos usando cadeias de caracteres URI.
Perguntas Frequentes
A aula “O Problema de HKT no TypeScript” é grátis?
Sim — o texto completo de “O Problema de HKT no TypeScript” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 4 aulas no total.
O que vou aprender em “O Problema de HKT no TypeScript”?
Entenda por que construtores de tipos genéricos são difíceis. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar TypeScript Academy?
Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “O Problema de HKT no TypeScript”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de TypeScript Academy?
Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- O Problema de HKT no TypeScript
- Definindo Construtores de Tipos
- O Padrão HKT Leve
- Functoras e Mapeadoras Genéricas