Query and check loop
Every dialect follows the same development loop: import its sql tag, write a static template, run the stable compiler check, then execute the unchanged query object through an application-owned driver or adapter.
Import from the selected grammar
| Database | Application import | Placeholder form |
|---|---|---|
| PostgreSQL | @typed-sql/postgres | $1, $2, … |
| MySQL | @typed-sql/mysql | ? |
| SQLite | @typed-sql/sqlite | ? |
Do not import sql from generated output. The configured grammar owns syntax, name resolution, built-ins, coercions, nullability, and diagnostics.
Write static SQL with parameter values
This checked PostgreSQL fixture selects a database enum and one bigint parameter:
import { sql } from "@typed-sql/postgres";
export const accountById = (accountId: bigint) => sql`
SELECT account.id, account.email, account.status
FROM users AS account
WHERE account.id = ${accountId}
`;The interpolation is always a value. It renders as $1 for PostgreSQL or ? for MySQL and SQLite; typed-sql never concatenates it into the SQL text.
Run the authoritative check
pnpm exec typed-sql check --project tsconfig.jsonThe compiler extracts the complete template, renders placeholders for the selected grammar, resolves it against the configured snapshot, and asks TypeScript to check the inferred overlay without rewriting source.
For the maintained PostgreSQL schema, the exact contract is:
type AccountByIdQuery = Query<
{ "id": bigint; "email": string; "status": "active" | "suspended"; },
readonly [bigint]
>;Query carries one row shape and an ordered tuple of all interpolated values. Adapter methods decide whether execution returns many rows, one row, or an optional row.
Reuse the contract
import type { QueryParameters, QueryRow } from "@typed-sql/core";
type Account = QueryRow<ReturnType<typeof accountById>>;
type AccountParameters = QueryParameters<ReturnType<typeof accountById>>;These utilities follow the compiler-proven query instead of duplicating a hand-written interface.
Observe the failure boundary
If the schema says id is bigint, this value fails the transformed TypeScript check:
const wrongId = "42";
sql`SELECT id FROM users WHERE id = ${wrongId}`;Unsupported, ambiguous, invalid, stale, or dynamic SQL resolves to a diagnostic or conservative unknown, never any or an optimistic guess. This is compile-time evidence; runtime result validation is separate and opt-in.
Continue with a complete path
Follow the PostgreSQL, MySQL, or SQLite quickstart to create schema evidence and execute the query. Then choose direct driver use or an adapter.