Summary
Procs, functions, and TVFs should be typed as tuples: [Args, ReturnType] instead of just Args.
Currently, the generic type maps only capture the input parameters:
type MyProcs = {
get_users: { department_id: number };
refresh_cache: void;
};
// Return type must be specified at every call site
const users = await ctx.proc<User>('get_users', { department_id: 1 });
Proposed: each entry becomes a tuple [Args, ReturnType]:
type MyProcs = {
get_users: [{ department_id: number }, User];
refresh_cache: void; // shorthand for [void, void]
};
// Return type is inferred when the tuple provides it
const users = await ctx.proc('get_users', { department_id: 1 }); // → User[]
// But the generic is still available for overriding or ad-hoc calls
const users = await ctx.proc<SpecialUser>('get_users', { department_id: 1 }); // → SpecialUser[]
await ctx.proc('refresh_cache'); // → void
Rules
SomeProc: [Args, ReturnType] — full tuple form
- If
Args is empty/unused, use void → [void, ReturnType]
- If
ReturnType is empty/unused, use void → [Args, void]
- Plain
void (no tuple) is shorthand for [void, void] — no args, no meaningful return
proc() and tvf() currently return T[] — with tuples, return becomes ReturnType[]
func() currently returns scalar T — with tuples, return becomes ReturnType
- The
T return type generic remains available — it defaults to the tuple's ReturnType but can be explicitly overridden at the call site
Behavior
- Tuple provides return type, no generic specified → infer from tuple
- Tuple provides return type, generic explicitly specified → generic wins (override)
- No tuple / plain
void → falls back to unknown (same as today), user specifies T manually
- Ad-hoc / untyped calls → user can still call
ctx.proc<MyType>(...) for procs not in the type map, or to override the mapped return type
Affected Surfaces
Context class generics: Context<DB, Procs, Funcs, Tvfs>
ctx.proc(), ctx.func(), ctx.tvf() method signatures
createContext<DB, Procs, Funcs, Tvfs>() factory
ImpersonatedScope<DB, Procs, Funcs, Tvfs> interface
- SDK type exports
Benefit
The type map becomes the single source of truth for both input and output shapes, eliminating repetitive annotations at call sites — while preserving full flexibility for ad-hoc calls and explicit overrides.
Summary
Procs, functions, and TVFs should be typed as tuples:
[Args, ReturnType]instead of justArgs.Currently, the generic type maps only capture the input parameters:
Proposed: each entry becomes a tuple
[Args, ReturnType]:Rules
SomeProc: [Args, ReturnType]— full tuple formArgsis empty/unused, usevoid→[void, ReturnType]ReturnTypeis empty/unused, usevoid→[Args, void]void(no tuple) is shorthand for[void, void]— no args, no meaningful returnproc()andtvf()currently returnT[]— with tuples, return becomesReturnType[]func()currently returns scalarT— with tuples, return becomesReturnTypeTreturn type generic remains available — it defaults to the tuple'sReturnTypebut can be explicitly overridden at the call siteBehavior
void→ falls back tounknown(same as today), user specifiesTmanuallyctx.proc<MyType>(...)for procs not in the type map, or to override the mapped return typeAffected Surfaces
Contextclass generics:Context<DB, Procs, Funcs, Tvfs>ctx.proc(),ctx.func(),ctx.tvf()method signaturescreateContext<DB, Procs, Funcs, Tvfs>()factoryImpersonatedScope<DB, Procs, Funcs, Tvfs>interfaceBenefit
The type map becomes the single source of truth for both input and output shapes, eliminating repetitive annotations at call sites — while preserving full flexibility for ad-hoc calls and explicit overrides.