Type Safety
Get compile-time validation, autocomplete, and runtime checks with genaql's TypeScript integration.
Defining Your Schema
Use defineSchema to declare your database structure:
schema.ts
import { defineSchema } from 'genaql';
export const schema = defineSchema({
users: {
id: 'serial',
name: 'text',
email: 'text',
role: { type: 'text', default: 'user' },
created_at: { type: 'timestamp', default: 'now()' },
updated_at: 'timestamp?' // nullable
},
posts: {
id: 'serial',
title: 'text',
content: 'text',
user_id: 'integer',
published: { type: 'boolean', default: false }
}
});Column Types
| genaql Type | TypeScript | PostgreSQL |
|---|---|---|
text | string | TEXT / VARCHAR |
integer | number | INTEGER |
serial | number | SERIAL |
boolean | boolean | BOOLEAN |
timestamp | Date | TIMESTAMP |
json | unknown | JSONB |
uuid | string | UUID |
Compile-Time Validation
TypeScript catches errors before your code runs:
validation.ts
// ✓ Valid - all columns exist
cook`main:users slay:id,name,email`
// ✗ Error - column doesn't exist
cook`main:users slay:id,name,nonexistent`
// ^^^^^^^^^^^
// Type Error: Column 'nonexistent' does not exist
// ✗ Error - table doesn't exist
cook`main:invalid_table slay:*`
// ^^^^^^^^^^^^^
// Type Error: Table 'invalid_table' does not existInferred Return Types
Query results are automatically typed based on your selection:
inferred.ts
const users = await db.query(
cook`main:users slay:id,name,email sus:active=true`
);
// TypeScript knows the shape:
// users: Array<{ id: number; name: string; email: string }>
users.forEach(user => {
console.log(user.name); // ✓ OK
console.log(user.invalid); // ✗ Error: Property 'invalid' does not exist
});Runtime Validation
Enable runtime checks for additional safety in development:
runtime.ts
import { createClient } from 'genaql';
const db = createClient({
dialect: 'postgres',
pool,
schema,
validate: process.env.NODE_ENV === 'development'
});
// In development, invalid queries throw helpful errors
// In production, validation is skipped for performanceBest Practice
Define your schema in a separate file and import it wherever you use genaql. This ensures consistent type checking across your entire codebase.