Skip to content

fix: precise types for $unsafeUnscoped chains and sql() payloads#26

Merged
benvinegar merged 1 commit into
mainfrom
fix/scoped-mutation-payload-types
Jun 28, 2026
Merged

fix: precise types for $unsafeUnscoped chains and sql() payloads#26
benvinegar merged 1 commit into
mainfrom
fix/scoped-mutation-payload-types

Conversation

@benvinegar

Copy link
Copy Markdown
Member

Summary

Two type-only precision fixes to the honest scoped-mutation facade already on main. No runtime change, no version bump — entries land under [Unreleased]. The 0.8.0 release that ships them is a separate stacked PR (#25), intended to merge after this one is reviewed.

The fixes

  1. .$unsafeUnscoped() return precision. It now returns UnscopedInsertBuilder<TRaw, TTable> instead of the bare TRaw. Conflict/upsert chains keep their exact per-dialect argument types but the trailing .returning(...) infers columns from the target table, instead of widening to Record<string, unknown>.
    • New helper ForwardChainMethod is the return-rewriting sibling of the existing ForwardMethod (types.ts): same dialect-gating, but it retypes the method's return to ScopedInsertResult so .returning() stays table-precise.
  2. sql template payloads. Scoped .values(...) / .set(...) now accept Drizzle sql expressions for individual column values (TableInsertValue maps each field to T | SQL), matching Drizzle's own insert/update signatures.

Why (evidence)

Built main as-is and overlaid it into a downstream consumer that uses both patterns. The two fixes map 1:1 to two independent typecheck-error families, and each is required:

Build overlaid into the consumer Result
main as-is fails — SQL<unknown> not assignable and widened-returning errors
main + sql-payload fix only 2 errors remain (the .$unsafeUnscoped()…returning() sites)
main + both fixes 0 errors (full typecheck passes)

Verification

format:check, lint, typecheck, test (44) all green. Diff is 2 files: src/types.ts and a ### Fixed block under [Unreleased] in CHANGELOG.md.

🤖 Generated with Claude Code

Two type-precision fixes on the honest scoped-mutation facade, both observed
as typecheck failures in a downstream consumer:

- `.$unsafeUnscoped()` now returns a builder (UnscopedInsertBuilder) whose
  conflict/upsert chains preserve the table-precise `.returning(...)` row type
  via ForwardChainMethod, instead of widening to `Record<string, unknown>`.
  ForwardChainMethod is the return-rewriting sibling of the existing
  ForwardMethod: it keeps each conflict method's exact per-dialect argument
  types but retypes the return to ScopedInsertResult so a trailing
  `.returning()` infers columns from the target table.
- Scoped `.values(...)` / `.set(...)` payloads accept Drizzle `sql` template
  expressions for individual column values, matching Drizzle's own mutation
  signatures (a raw SQL column value was previously rejected).

No runtime change and no version bump — entries land under [Unreleased]; the
release that ships them is cut separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@benvinegar benvinegar mentioned this pull request Jun 28, 2026
@benvinegar benvinegar merged commit 77e0869 into main Jun 28, 2026
4 checks passed
@benvinegar benvinegar mentioned this pull request Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant