Skip to content

fix ControlledTransaction<infer DB, any> inferring DB as string - #1967

Open
igalklebanov wants to merge 2 commits into
speed-up-transaction-type-checksfrom
fix/controlled-transaction-infer-any
Open

fix ControlledTransaction<infer DB, any> inferring DB as string#1967
igalklebanov wants to merge 2 commits into
speed-up-transaction-type-checksfrom
fix/controlled-transaction-infer-any

Conversation

@igalklebanov

@igalklebanov igalklebanov commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes an inference regression introduced by the Transaction/ControlledTransaction intersection rewrite in this branch, and removes the branch's one remaining perf regression while at it.

Problem: T extends ControlledTransaction<infer DB, any> ? DB : never silently infers DB as string instead of the actual database type. The bogus candidate leaks out of releaseSavepoint's return type: with S instantiated as any, the ReleaseSavepoint utility's recursion stays a deferred conditional and poisons structural inference. RollbackToSavepoint is immune because its success branch returns S rather than the inferred tuple prefix.

Fix: short-circuit ReleaseSavepoint to string[] when S is any (0 extends 1 & S guard).

Perf

Measured like the table in #1962: tsc --noEmit --extendedDiagnostics per assignability case, three runs each. "Before" is this branch's current head (808047a), "after" adds this commit. Measured with --skipLibCheck and a minimal two-table fixture, so instantiation counts isolate the assignability work itself (which is why the cheap cases show tens instead of ~12k).

Case TS Instantiations (before → after) Check time (before → after)
Kysely assignable to Kysely 5.9 0 → 0 10ms → 10ms
6.0 0 → 0 10ms → 10ms
7.0 0 → 0 1ms → 1ms
Transaction assignable to Kysely 5.9 28 → 28 10ms → 10ms
6.0 28 → 28 10ms → 10ms
7.0 28 → 28 1ms → 1ms
ControlledTransaction assignable to Kysely 5.9 43 → 43 10ms → 10ms
6.0 43 → 43 10ms → 10ms
7.0 43 → 43 1ms → 1ms
ControlledTransaction assignable to Transaction 5.9 313,676 → 139,288 ~400ms → ~220ms
6.0 327,643 → 152,953 ~430ms → ~245ms
7.0 336,103 → 160,884 ~141ms → ~68ms

The guard halves the ControlledTransaction assignable to Transaction case because the same deferred conditional that poisoned inference was also doing work during assignability checking. Going by the numbers in #1962, that case is now faster than master's class design (260-290ms on stable TS), so the trade-off flagged there as debatable no longer exists. The ts-benchmark baseline is updated to the new count.

Verified

pnpm build, pnpm test:typings, ts-benchmarks (clean, one improved baseline), plus targeted probes for <infer D, any>, <infer D, infer S>, <infer D>, <infer D, string[]>, <any, infer S> and ReleaseSavepoint tuple correctness, on both TypeScript 7.0.2 and 5.4 (oldest supported).

🤖 Generated with Claude Code

When `S` is instantiated as `any`, `ReleaseSavepoint`'s deferred
conditional in `releaseSavepoint`'s return type leaked a bogus `string`
inference candidate into `infer DB`. Short-circuit `ReleaseSavepoint` to
`string[]` when `S` is `any`.

Side effect: `ControlledTransaction` assignable to `Transaction` dropped
from 330097 to 155377 instantiations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
kysely Ready Ready Preview Aug 3, 2026 11:55pm

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Aug 3, 2026

Copy link
Copy Markdown

commit: 2e4f5a9

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

⏱️ TypeScript Benchmark Results

✅ ⏱️  No benchmark changes detected.

@igalklebanov igalklebanov added typescript Related to Typescript performance issue Something is slow af labels Aug 3, 2026
@igalklebanov
igalklebanov requested a review from koskimas August 3, 2026 22:47
Covers `savepoint`/`rollbackToSavepoint`/`releaseSavepoint` savepoint-list
typing, invalid-name rejection, the `S = any` degradation of
`releaseSavepoint` to `string[]`, and `infer` patterns over
`ControlledTransaction`/`Transaction`. The `S = any` and `infer DB`
assertions fail without the `ReleaseSavepoint` guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance issue Something is slow af typescript Related to Typescript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant