Quick start
This page takes you from an empty project to a typed query in a few minutes.
Try it first
Open the example in the TypeScript Playground to edit the SQL and hover the types, with nothing to install. The Playground runs TypeScript 6, which TypeSQL does not support, so treat it as a demo.
1. Install
This page uses node-postgres. Installation covers postgres.js, other package managers and the requirements.
npm install @typesql/core @typesql/pg pg
npm install -D typescript@7.1.0-beta2. Describe your tables
A schema is a TypeScript interface. Each key is a table, and each column has a type name from your database.
import type { Col } from "@typesql/core/postgres";
export interface DB {
users: {
id: Col<"int4", { hasDefault: true }>;
email: Col<"text">;
display_name: Col<"text", { nullable: true }>;
created_at: Col<"timestamptz", { hasDefault: true }>;
};
posts: {
id: Col<"int8", { hasDefault: true }>;
author_id: Col<"int4">;
title: Col<"text">;
};
}Colis aNOT NULLcolumn.{ nullable: true }allowsNULL.{ hasDefault: true }means it has a default (serial, identity,DEFAULT …), soINSERTcan leave it out.
You can also generate it from a live database, derive it from your migrations, or take it from Kysely, Drizzle or Prisma. Declaring tables lists every column helper.
3. Create sql
Pass the schema and your driver's client to createSql:
import { Pool } from "pg";
import { createSql } from "@typesql/pg";
const pool = new Pool({ connectionString: process.env["DATABASE_URL"] });
const sql = createSql<DB>(pool);4. Write a query
const recent = sql(
`SELECT u.id, u.email, p.title
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
WHERE u.created_at > $1`,
new Date("2026-01-01"),
);The LEFT JOIN makes title nullable, because a user may have no posts. $1 takes the type of created_at, so it accepts a Date.
5. Run it
const rows = await recent.execute();
const user = await sql(
"SELECT email, display_name FROM users WHERE id = $1",
7,
).executeTakeFirstOrThrow();executeTakeFirstOrThrow() throws a NoResultError when there is no row. node-postgres lists all the execute* methods.
The text goes to the database as you wrote it, and the values go as parameters:
recent.text;
recent.values;6. Mistakes are compile errors
When the SQL is wrong, the error appears on the string, worded like the database's error:
sql("SELECT emial FROM users");
sql("SELECT id FROM users WHERE id = $1", "7");The number after the message is the position of the wrong token. Errors and troubleshooting explains how to read these.
Next steps
- Selecting data: joins, nullability, aggregates and JSON.
- Parameters:
$1,:nameand inline${sql.param(value)}. - Inserting and updating:
INSERT,UPDATE,DELETEandRETURNING. - Dynamic SQL: build statements from pieces.
- Editor support for VS Code and Neovim: completions and highlighting inside your SQL strings.