Summary
In strict mode, WhereScan (src/where.ts:67-84) only validates the token immediately before a trigger operator (=, LIKE, IN, BETWEEN, IS, …). Because the recursive pattern S extends \${infer Head} ${infer Tail}`requires a trailing space to keep recursing, the very last token of a WHERE clause is never fed throughValidateWhereOperand` — there's no operator after it to trigger the check.
Repro
type Q = StrictQuery<DB, 'select id from users where age = naem'>
// naem is an unknown column, but Q resolves to { id: number }[] — no QueryTypeError
Compare with the symmetric, already-covered case where the typo is on the LHS (where naem = 'x'), which does correctly produce QueryTypeError<'unknown column: naem'>[] (see tests/where-strict.test-d.ts:19-24). Swapping operand order defeats the check.
Impact
Any WHERE-clause typo that lands as the final operand of the clause (not just the last condition — the last word) is silently accepted. This is a common shape: where id = someMisspelledColumn, ... and status = statys, etc. Since this is strict mode's core promise (catch unknown columns at compile time), a false negative here is worse than no check at all — it gives a false sense of safety.
Where
src/where.ts:67-84 (WhereScan) — the operand-tracking Prev never gets validated once there's no subsequent operator to trigger it.
Summary
In strict mode,
WhereScan(src/where.ts:67-84) only validates the token immediately before a trigger operator (=,LIKE,IN,BETWEEN,IS, …). Because the recursive patternS extends \${infer Head} ${infer Tail}`requires a trailing space to keep recursing, the very last token of a WHERE clause is never fed throughValidateWhereOperand` — there's no operator after it to trigger the check.Repro
Compare with the symmetric, already-covered case where the typo is on the LHS (
where naem = 'x'), which does correctly produceQueryTypeError<'unknown column: naem'>[](seetests/where-strict.test-d.ts:19-24). Swapping operand order defeats the check.Impact
Any WHERE-clause typo that lands as the final operand of the clause (not just the last condition — the last word) is silently accepted. This is a common shape:
where id = someMisspelledColumn,... and status = statys, etc. Since this is strict mode's core promise (catch unknown columns at compile time), a false negative here is worse than no check at all — it gives a false sense of safety.Where
src/where.ts:67-84(WhereScan) — the operand-trackingPrevnever gets validated once there's no subsequent operator to trigger it.