Skip to content

Inference and safety

typed-sql fails closed. A query receives an exact type, a conservative unknown, or a diagnostic. It never receives a plausible but unproven row or parameter type.

Inference outcomes

Exact

The complete row, ordered parameter tuple, result kind, and relevant nullability are proven from the SQL grammar and generated schema.

ts
Query<
  { id: bigint; email: string; budget: string | null },
  readonly [bigint]
>

Unknown

Analysis has insufficient evidence for a row property or parameter position. That position becomes unknown. This preserves safety while allowing valid SQL outside the current inference surface.

Diagnostic

Invalid, ambiguous, conflicting, stale, malformed, or deliberately unsupported SQL produces a stable diagnostic code and source range. The compiler does not emit a confident query overlay for that statement.

Nullability

Nullability follows both catalog metadata and SQL structure. A nullable column and a column from the nullable side of an outer join become T | null. Aggregate and function nullability belong to the selected grammar.

Parameters

Each interpolation is resolved from its SQL context and stored in placeholder order. Positions without enough evidence remain unknown. Query values are always rendered as driver parameters unless the developer selects an explicit structural API.

Trusted structure

sql.fragment, sql.ident(), and sql.raw() are distinct trust boundaries:

  • sql.fragment marks static template structure while preserving nested values as parameters.
  • sql.ident() delegates safe identifier quoting to the grammar.
  • sql.raw() inserts trusted SQL unchanged and is not an escaping API.

A nested JavaScript template is not trusted SQL by itself. When used as a structural branch, it produces TSQ004 and can be changed to sql.fragment explicitly.

Dynamic SQL

Use sql.dynamic() for SQL whose structure cannot be represented statically. Its row type is deliberately unknown. Arbitrary strings are never promoted to statically trusted structure.

Runtime trust boundaries

Static types describe the configured schema and adapter policy. They do not validate untrusted request payloads, data written outside database constraints, or serialized responses. Add runtime validation wherever application trust boundaries require it.

Resource limits

The tokenizer, parser, structural expansion, workspace scan, and editor caches are bounded. Limit violations produce diagnostics rather than unbounded CPU or memory use. See Diagnostics and Performance.

Released under the MIT License.