Diseño de un DSL fluido de consultas
Cree una API de consultas encadenable y con validación propia.
Diseño de un DSL fluido de consultas es una lección gratuita de TypeScript Academy en CoddyKit. Esta es la lección 2 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.
Diseñar un DSL fluido de consultas
Diseñamos un DSL de consultas encadenable en el que cada paso refina los pasos siguientes permitidos mediante los tipos de retorno. El resultado se lee como SQL y rechaza los órdenes no válidos durante la compilación.
La gramática objetivo
Queremos: from, seguido de un where opcional y repetible, y después un select terminal. No puede usar select antes de from ni usar from dos veces.
Interfaces de estado
Modele cada etapa como una interfaz que devuelve la etapa siguiente.
interface Builder {
from(table: string): FromStage;
}
interface FromStage {
where(cond: string): FromStage; // repeatable
select(...cols: string[]): Result;
}
interface Result { sql: string; }Exigir el orden
Como select solo existe en FromStage, llamarlo sobre el Builder inicial produce un error de compilación. El orden se impone únicamente mediante los métodos que expone cada etapa.
declare const db: Builder;
db.from("users").select("id"); // ok
db.select("id"); // Error: select missing on BuilderSeguimiento de las columnas seleccionadas
Añada un genérico fantasma para recordar qué columnas se seleccionaron, de modo que el tipo de resultado sea 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[]; }Refinar con cada llamada
Cada where también puede acumular restricciones en el tipo. Aquí lo mantenemos sencillo, pero el patrón se generaliza para hacer un seguimiento de los parámetros enlazados.
const q = db.from("users").where("age > 18").where("active = true");
// still FromStage; select remains availableImpedir repetir from
Como FromStage no expone from, no puede llamarlo dos veces. La gramática lo prohíbe estructuralmente, sin necesidad de una protección en tiempo de ejecución.
db.from("a").from("b"); // Error: from does not exist on FromStageUn paso terminal
select devuelve Result, que no expone ni where ni from, por lo que termina la cadena. Solo quedan disponibles las operaciones de lectura del resultado.
const r = db.from("users").select("id", "name");
r.columns; // ("id" | "name")[]
// r.where(...) -> Error: where not on ResultRestricciones de columnas con tipos
Restrinja las columnas a un esquema de tabla conocido mediante otro genérico, de modo que se rechacen las columnas desconocidas y este DSL se combine con las ideas de ORM anteriores.
interface Table<Cols extends string> {
select<C extends Cols>(...cols: C[]): Result<C>;
}
// db.from gives Table<"id" | "name" | "age">Pasos opcionales frente a obligatorios
Haga que un paso sea obligatorio exponiendo el método siguiente únicamente después de ese paso. Por ejemplo, fuerce al menos un where devolviendo una etapa cuyo select solo aparezca después de llamar a where. Estos mismos tipos encadenados también pueden inferir el tipo de fila del resultado de ejecutar la consulta, conectando la gramática en tiempo de compilación con los datos en tiempo de ejecución.
Por qué es importante
Un DSL fluido diseñado de esta forma se documenta por sí mismo y es imposible de utilizar incorrectamente: el autocompletado muestra solo los pasos siguientes válidos y las secuencias ilegales nunca se compilan. Esta es la base de las bibliotecas de generadores ergonómicos.
Comprobación rápida
Confirme su comprensión del diseño de DSL fluidos.
Resumen
Diseñó un DSL fluido de consultas como una máquina de estados en el nivel de tipos: cada interfaz de etapa devuelve la siguiente y expone únicamente los métodos válidos. Los genéricos fantasma hacen un seguimiento de las columnas seleccionadas, las etapas terminales finalizan la cadena y las restricciones de columnas rechazan los nombres desconocidos; todo ello se impone mediante los tipos de retorno.
Preguntas frecuentes
¿La lección «Diseño de un DSL fluido de consultas» es gratis?
Sí — el texto completo de «Diseño de un DSL fluido de consultas» 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 «Diseño de un DSL fluido de consultas»?
Cree una API de consultas encadenable y con validación propia. 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 2 de 4.
¿Cuánto tiempo toma la lección «Diseño de un DSL fluido de consultas»?
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
- Qué es un DSL a nivel de tipos
- Diseño de un DSL fluido de consultas
- Validación de entradas en tiempo de compilación
- Mensajes de error en DSL a nivel de tipos