sqltype
Ultra-fast, zero-runtime SQL-to-TypeScript compiler.
Write raw PostgreSQL queries with compile-time type safety. Zero Docker containers. Zero WASM overhead. Sub-10ms codegen.
Why sqltype?
Modern TypeScript database tools often force an undesirable trade-off:
- ORMs (Prisma, Drizzle) introduce proprietary query DSLs, runtime overhead, and complex migration engines.
- PgTyped requires an active PostgreSQL connection or Docker instance running during compilation to infer types.
- sqlc-gen-typescript runs heavy 69MB WASM blobs in Node.js, introducing significant compile-time latency.
sqltype eliminates these compromises. By utilizing PostgreSQL's native C-parser (libpg_query) via Rust, sqltype parses raw migration DDL files to build an exact in-memory schema catalog and analyzes SQL query ASTs in sub-10ms, emitting clean, zero-dependency TypeScript types and SQL constants.
Comparison
| Feature | sqltype |
PgTyped | sqlc (TS) | Prisma |
|---|---|---|---|---|
| Running Database Required | No (Offline AST) | Yes (Docker / Postgres) | No | No (Dev schema engine) |
| Codegen Speed | < 10ms (Native Rust) | 200–800ms (Network roundtrip) | 2–3s (69MB WASM) | 1–3s (Node / WASM) |
| Runtime Overhead | 0 KB (Pure types & strings) | Runtime helper | 0 KB | Heavy client library & engine |
| Outer Join Nullability | Automatic (AST traversal) | Manual overrides / Flaky | Manual casts | Handled |
| CTE / Subquery Support | Automatic (Scope overlay) | Partial | Partial | Proprietary syntax |
| Sub-5ms Watch Mode | Yes (Incremental) | No | No | Partial |
Key Features
- Ultra-Fast Performance: Written in native Rust; generates types for dozens of queries in milliseconds.
- Deterministic DDL Processing: Sequentially parses raw migration files (
.sql) to track table structures, constraints, primary keys, and column alterations (ALTER TABLE ADD / DROP / ALTER TYPE). - Accurate Join Nullability:
LEFT JOIN: Right-hand table projections are automatically marked| null.RIGHT JOIN: Left-hand table projections are automatically marked| null.FULL JOIN: Both sides are automatically marked| null.
- Common Table Expressions (CTEs): Analyzes
WITHclauses recursively, registering CTE column types and nullabilities into a temporary query catalog overlay. - Expression & Function Resolution:
- Evaluates arithmetic expressions (
+,-,*,/) tonumber. - Statically evaluates
COALESCE(a, b): if any argument is non-nullable, the result is non-nullable. - Correctly maps PostgreSQL array types (
text[],int4[]) to TypeScript array types (string[],number[]). - Distinguishes aggregate nullability:
COUNT(...)is strictlynumber, whileSUM(...)/AVG(...)resolve tonumber | null.
- Evaluates arithmetic expressions (
- Zero-Dependency Output: Emits standard TypeScript interfaces and typed query objects compatible with
pg,@vercel/postgres,postgres.js, or@neondatabase/serverless. - Sub-5ms Watch Mode: Re-compiles only changed queries incrementally in
< 5ms.
Quickstart
1. Installation
Install globally or as a project devDependency via npm:
# Using npm
npm install -D sqltype
# Using pnpm
pnpm add -D sqltype
# Using cargo
cargo install sqltype
2. Directory Structure
Organize your migrations and queries as raw .sql files:
my-project/
├── migrations/
│ ├── 001_create_users.sql
│ └── 002_create_posts.sql
├── queries/
│ ├── get_user_with_posts.sql
│ └── find_posts_by_status.sql
└── src/
└── types/
└── (generated .ts files emitted here)
3. Example SQL Query
Annotate your query with -- name: <QueryName>:
-- queries/get_user_with_posts.sql
-- name: GetUserWithPosts
SELECT
u.id,
u.email,
p.title AS post_title,
COUNT(c.id) AS comment_count
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
LEFT JOIN comments c ON c.post_id = p.id
WHERE u.id = $1
GROUP BY u.id, u.email, p.title;
4. Run sqltype
Validate queries against your migrations (CI/CD):
sqltype check --migrations ./migrations --queries ./queries
Exits with code 0 on success, or code 1 with descriptive errors on type or column mismatch.
Generate TypeScript files:
sqltype generate --migrations ./migrations --queries ./queries --out ./src/types
Run Watch Mode for Instant Feedback:
sqltype generate --migrations ./migrations --queries ./queries --out ./src/types --watch
Watches for changes in --queries and re-generates individual query files in sub-5ms.
Generated Output
sqltype emits zero-dependency, type-safe TypeScript:
// Autogenerated by sqltype. DO NOT EDIT.
export interface GetUserWithPostsParams {
id: string;
}
export interface GetUserWithPostsRow {
id: string;
email: string;
post_title: string | null;
comment_count: number;
}
export const getUserWithPostsSql = `
SELECT
u.id,
u.email,
p.title AS post_title,
COUNT(c.id) AS comment_count
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
LEFT JOIN comments c ON c.post_id = p.id
WHERE u.id = $1
GROUP BY u.id, u.email, p.title;
`;
export type GetUserWithPostsQuery = {
sql: string;
params: GetUserWithPostsParams;
row: GetUserWithPostsRow;
};
Usage in Application Code
Works seamlessly with any PostgreSQL client (e.g. pg, postgres.js):
import { Pool } from "pg";
import { getUserWithPostsSql, GetUserWithPostsRow } from "./types/get_user_with_posts";
const pool = new Pool();
async function getUser(id: string): Promise<GetUserWithPostsRow[]> {
const result = await pool.query<GetUserWithPostsRow>(getUserWithPostsSql, [id]);
return result.rows;
}
CLI Reference
Usage: sqltype <COMMAND>
Commands:
check Validates all queries against the migration schema and exits with code 1 on type/column mismatch
generate Emits .ts files for all valid queries
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
sqltype check
-m, --migrations <DIR>: Directory containing PostgreSQL migration.sqlfiles.-q, --queries <DIR>: Directory containing application.sqlquery files.
sqltype generate
-m, --migrations <DIR>: Directory containing PostgreSQL migration.sqlfiles.-q, --queries <DIR>: Directory containing application.sqlquery files.-o, --out <DIR>: Destination directory for generated.tsfiles.-w, --watch: Run watcher with sub-5ms incremental re-compilation.
License
MIT DeepMind Agentic Team