ClickHouse Query Builder

The TypeScript-first ClickHouse query builder

Write composable, type-safe ClickHouse queries. Types are generated from your live schema — including correct ClickHouse-to-TypeScript mappings for DateTime, UInt64, Nullable, and Decimal. No SQL strings. No hand-written interfaces.

Type source

Generated from schema

ClickHouse syntax

Native support

Best for

Analytics-heavy TS apps

ClickHouse types do not map cleanly to TypeScript

DateTime comes back as a string, not a Date. UInt64 comes back as a string. If you write your own interfaces, you're guessing — and TypeScript trusts you. hypequery generates types from the live schema so they're always right.

SQL strings do not scale across a codebase

The same analytics query ends up duplicated in API routes, background jobs, dashboards, and internal tools. A query builder with composable, reusable definitions removes that drift.

Generic query builders are not built for ClickHouse

Tools built for Postgres need adapting for ClickHouse. PREWHERE, ARRAY JOIN, dictGet(), withScalar CTEs, SAMPLE — these need native support, not workarounds.

How hypequery works

Generate types from ClickHouse, then build composable queries

Run npx @hypequery/cli generate against your ClickHouse instance. You get a typed schema file that maps every table and column to the correct TypeScript type. Then build queries with a fluent builder that understands ClickHouse natively.

  • Schema types generated from your live ClickHouse database
  • Correct runtime type mappings — DateTime→string, UInt64→string, Nullable→T|null
  • Composable builder with conditional filters and reusable query fragments
  • Full ClickHouse-native syntax: PREWHERE, ARRAY JOIN, CTEs, dictGet(), SAMPLE
  • Same query definition runs inline, over HTTP, or as a React hook

Query builder

Typed queries from generated schema

how-hypequery-works.ts

Types come from the schema, not from hand-written interfaces. When the schema changes and you regenerate, TypeScript catches the mismatch at compile time.

Multi-context execution

Define once, execute in any context

The query builder is one part of hypequery. The same query definition that runs inline can also be served as an HTTP endpoint with OpenAPI docs, or wrapped in a typed React hook — without rewriting anything.

This is the core difference between a query builder and an analytics layer. A query builder helps you write queries. An analytics layer makes those queries reusable across your entire product.

If you are comparing options, the blog post walks through @clickhouse/client, Kysely, Cube, and hypequery side by side.

Multi-context

One query definition, three execution contexts

multi-context-execution.ts

Define it once. Run it inline for scripts and tests, serve it over HTTP for dashboards, or wrap it in a React hook for interactive components.

Why teams search for this

Common implementation questions this page should solve

ClickHouse query builder TypeScript

The key question is not just syntax — it's whether the builder understands ClickHouse runtime types and can be reused across your app. hypequery is the only option built specifically for ClickHouse + TypeScript.

Type-safe ClickHouse queries

Type safety in ClickHouse starts with getting the mappings right. DateTime, UInt64, Decimal, and Nullable columns all behave differently from what TypeScript might assume. Generated schema types fix this at the source.

ClickHouse vs Kysely

Kysely is excellent for Postgres. For ClickHouse-primary analytics, the lack of native ClickHouse syntax and schema introspection means you'll be working around its edges. See the full comparison in the blog post.

ClickHouse HTTP API TypeScript

If you want a typed HTTP API on top of ClickHouse without writing a custom layer, @hypequery/serve exposes query definitions as HTTP endpoints with OpenAPI docs automatically.

Next step

Start with schema generation

Generate TypeScript types from your live ClickHouse schema. Then build your first typed query, and decide whether to run it inline or expose it over HTTP.