O Padrão HKT Leve
Implemente o truque de desfuncionalização Kind/URI.
O Padrão HKT Leve é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 3 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.
Defuncionalização
O truque por trás da codificação tem um nome: defuncionalização. Em vez de uma função de tipo real de ordem superior, representamos cada função por um rótulo e a resolvemos com uma única consulta de primeira ordem. O registro URItoKind é essa tabela de consulta.
type Kind<F extends URIS, A> = URItoKind<A>[F];
// One lookup replaces true type-function applicationO Tipo Kind
Kind<F, A> é a face pública do padrão. Leia-o como "o construtor F aplicado a A". Ele oculta a indexação do registro por trás de um nome claro.
type A = Kind<"Array", number>; // number[]
type B = Kind<"Option", string>; // string | nullRestringindo o Construtor a URIS
F precisa ser uma URI registrada. Restrinja-o com extends URIS para que apenas rótulos válidos possam ser usados e erros de digitação se tornem erros de compilação.
type Kind<F extends URIS, A> = URItoKind<A>[F];
// Kind<"Arrey", number> -> error, not a valid URIEscrevendo Assinaturas Genéricas
Agora podemos escrever a assinatura de Functor que antes era impossível. Substitua cada F<A> por Kind<F, A> e o compilador a aceitará.
interface Functor<F extends URIS> {
map<A, B>(fa: Kind<F, A>, f: (a: A) => B): Kind<F, B>;
}A Resolução em Ação
Quando você fixa F em uma URI concreta, Kind é resolvido para o tipo real do contêiner. Um Functor<"Array"> tem um map de A[] para B[].
type ArrayFunctor = Functor<"Array">;
// map: <A, B>(fa: A[], f: (a: A) => B) => B[]Múltiplos Argumentos de Tipo
Alguns construtores recebem dois argumentos, como Either<E, A>. O fp-ts estende o padrão com URItoKind2 e Kind2<F, E, A> para o tipo * -> * -> *. A ideia se amplia com a adição de mais registros.
interface URItoKind2<E, A> {
Either: { left: E } | { right: A };
}
type Kind2<F extends URIS2, E, A> = URItoKind2<E, A>[F];A Convenção do fp-ts
O fp-ts estabeleceu a convenção seguida por todo este curso: uma cadeia de caracteres URI por tipo de dados, um registro URItoKind estendido por fusão de declarações e Kind para a resolução. Reconhecê-la permite que você leia assinaturas de tipos do fp-ts e do Effect.
// In fp-ts you will see exactly:
// declare module "fp-ts/HKT" { interface URItoKind<A> { ... } }Um Registro de Instância
Uma "instância" de uma abstração é um valor que a implementa para uma URI específica. A instância carrega o map concreto. Na próxima lição, escreveremos a instância de vetor; aqui está seu formato.
declare const arrayFunctor: Functor<"Array">;
const out = arrayFunctor.map([1, 2, 3], n => n * 2); // number[]Por Que Isso É "Leve"
Ele é chamado de padrão de HKT leve porque não precisa de alterações no compilador nem de sintaxe especial, apenas de interfaces e acesso indexado. O custo é um pouco de formalidade (URIS e registros) em troca de código realmente genérico para contêineres.
type Kind<F extends URIS, A> = URItoKind<A>[F];
// No magic, just a typed lookup tableLimitações
O padrão é prolixo, e as mensagens de erro podem ser enigmáticas porque mencionam a codificação em vez do seu domínio. Ele também exige que cada contêiner seja registrado. Na maioria dos aplicativos, você consome bibliotecas que já fazem isso em vez de construir tudo por conta própria.
// Trade-off: real abstraction power vs. encoding ceremonyReunindo Tudo
A receita completa do HKT leve: defina uma URI, registre-a em URItoKind, defina abstrações usando Kind<F, A> e forneça instâncias por URI. Esse é todo o conjunto de ferramentas por trás das bibliotecas funcionais genéricas em TypeScript.
type Kind<F extends URIS, A> = URItoKind<A>[F];
interface Functor<F extends URIS> {
map<A, B>(fa: Kind<F, A>, f: (a: A) => B): Kind<F, B>;
}Verificação Rápida
Teste sua compreensão do padrão HKT leve.
Recapitulação
Você montou o padrão HKT leve.
- A defuncionalização substitui a aplicação de funções de tipo por uma consulta.
Kind<F, A>resolve uma URI e um argumento para um tipo concreto.- As assinaturas genéricas usam
Kindem vez deF<A>. - O padrão se amplia para dois argumentos por meio de
Kind2e é a convenção do fp-ts.
Próximo: um map genérico com instâncias reais.
Perguntas Frequentes
A aula “O Padrão HKT Leve” é grátis?
Sim — o texto completo de “O Padrão HKT Leve” é 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 Padrão HKT Leve”?
Implemente o truque de desfuncionalização Kind/URI. 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 3 de 4.
Quanto tempo leva a aula “O Padrão HKT Leve”?
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