0Pricing
TypeScript Academy · Aula

Projetando uma DSL Fluente de Consultas

Crie uma API de consultas encadeável e que valide a si mesma.

Projetando uma DSL Fluente de Consultas é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 2 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.

Projetando uma DSL fluente de consultas

Projetamos uma DSL de consultas encadeável na qual cada etapa refina as próximas etapas permitidas por meio de tipos de retorno. O resultado se lê como SQL e rejeita ordenações inválidas em tempo de compilação.

Gramática-alvo

Queremos: from seguido de um where opcional (repetível) e depois um select terminal. Não é possível usar select antes de from, nem usar from duas vezes.

Interfaces de estado

Modele cada etapa como uma interface que retorna a etapa seguinte.

interface Builder {
  from(table: string): FromStage;
}
interface FromStage {
  where(cond: string): FromStage; // repeatable
  select(...cols: string[]): Result;
}
interface Result { sql: string; }

Impondo a ordem

Como select existe apenas em FromStage, chamá-lo no Builder inicial é um erro de compilação. A ordem é imposta puramente pelos métodos que cada etapa expõe.

declare const db: Builder;
db.from("users").select("id"); // ok
db.select("id");               // Error: select missing on Builder

Acompanhando colunas selecionadas

Adicione um genérico fantasma para lembrar quais colunas foram selecionadas, de modo que o tipo do resultado seja preciso.

interface FromStage<T extends string = never> {
  where(c: string): FromStage<T>;
  select<C extends string>(...cols: C[]): Result<C>;
}
interface Result<C extends string> { columns: C[]; }

Refinando a cada chamada

Cada where também pode acumular restrições no tipo. Aqui mantemos a simplicidade, mas o padrão se generaliza para acompanhar parâmetros vinculados.

const q = db.from("users").where("age > 18").where("active = true");
// still FromStage; select remains available

Impedindo a repetição de from

Como FromStage não expõe from, você não pode chamá-lo duas vezes. A gramática o proíbe estruturalmente, sem necessidade de uma proteção em tempo de execução.

db.from("a").from("b"); // Error: from does not exist on FromStage

Etapa terminal

select retorna Result, que não expõe nem where nem from, encerrando a cadeia. Restam apenas operações de leitura do resultado.

const r = db.from("users").select("id", "name");
r.columns; // ("id" | "name")[]
// r.where(...) -> Error: where not on Result

Restrições de colunas tipadas

Restrinja colunas a um esquema de tabela conhecido com outro genérico, para que colunas desconhecidas sejam rejeitadas, combinando esta DSL com as ideias anteriores de ORM.

interface Table<Cols extends string> {
  select<C extends Cols>(...cols: C[]): Result<C>;
}
// db.from gives Table<"id" | "name" | "age">

Etapas opcionais e obrigatórias

Torne uma etapa obrigatória expondo apenas o método seguinte depois dela. Por exemplo, force pelo menos um where retornando uma etapa cujo select só apareça depois que where for chamado. Os mesmos tipos encadeados também podem inferir o tipo da linha de resultado da execução da consulta, vinculando a gramática em tempo de compilação aos dados em tempo de execução.

Por que isso importa

Uma DSL fluente projetada dessa forma é autodocumentada e impossível de usar incorretamente: o preenchimento automático mostra apenas as próximas etapas válidas, e sequências ilegais nunca são compiladas. Essa é a base de bibliotecas de construtores ergonômicas.

Verificação rápida

Confirme sua compreensão do design de DSLs fluentes.

Recapitulação

Você projetou uma DSL fluente de consultas como uma máquina de estados em nível de tipos: a interface de cada etapa retorna a seguinte, expondo apenas métodos válidos. Genéricos fantasmas acompanham as colunas selecionadas, etapas terminais encerram a cadeia e restrições de colunas rejeitam nomes desconhecidos, tudo imposto pelos tipos de retorno.

Perguntas Frequentes

A aula “Projetando uma DSL Fluente de Consultas” é grátis?

Sim — o texto completo de “Projetando uma DSL Fluente de Consultas” é 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 “Projetando uma DSL Fluente de Consultas”?

Crie uma API de consultas encadeável e que valide a si mesma. 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 2 de 4.

Quanto tempo leva a aula “Projetando uma DSL Fluente de Consultas”?

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

  1. O que é uma DSL no Nível de Tipos
  2. Projetando uma DSL Fluente de Consultas
  3. Validação de Entrada em Tempo de Compilação
  4. Mensagens de Erro em DSLs no Nível de Tipos
← Voltar para TypeScript Academy