SqlType

infers the result type of a SQL query at compile time, using only TypeScript's type system.

SqlType is a static SQL analysis and inference engine implemented entirely with TypeScript’s type system. it parses SQL-like query strings at compile time and infers the resulting data shape based on a provided schema. the system supports validation of selectors, function calls, joins, aliases, and SELECT * semantics - all within the type layer of TypeScript, with zero runtime logic. SqlType helps developers catch query issues during development, creating safer and more predictable data access layers in TypeScript-based systems.

features

  • compile-time SQL parsing

    parses and analyzes SQL queries entirely at the type level using recursive conditional types.

  • full query shape inference

    infers result structures from SELECT queries, including expressions and function calls.

  • support for joins and aliases

    supports INNER, LEFT, RIGHT, and FULL OUTER JOINs with alias resolution and field mapping.

  • function usage validation

    functions like COUNT(...) are checked at compile time for valid argument types and nesting.

  • zero-runtime

    no runtime dependency; the entire system works within TypeScript’s type checker.

usage

// Example 1: Simple SELECT with alias
type Tables = {
  users: {
    id: number;
    name: string;
  };
};

type Query = "SELECT users.name AS username FROM users";

type Result = BuildQuery<Query, Tables>;

/*
  Result:
  {
    username: string;
  }
*/
// Example 2: COUNT aggregation with JOIN
type Tables = {
  users: {
    id: number;
    name: string;
  };
  posts: {
    id: number;
    user_id: number;
  };
};

type Query = "SELECT COUNT(posts.id) AS totalPosts FROM users LEFT JOIN posts ON users.id = posts.user_id";

type Result = BuildQuery<Query, Tables>;

/*
  Result:
  {
    totalPosts: number;
  }
*/
// Example 3: Multiple columns with alias and join
type Tables = {
  users: {
    id: number;
    name: string;
  };
  posts: {
    id: number;
    user_id: number;
    title: string;
  };
};

type Query = "SELECT u.name AS username, COUNT(p.id) AS total FROM users u LEFT JOIN posts p ON u.id = p.user_id";

type Result = BuildQuery<Query, Tables>;

/*
  Result:
  {
    username: string;
    total: number;
  }
*/

stack

TypeScript, TypeScript type-level programming