Skip to content

Instantly share code, notes, and snippets.

@bryanprimus
Created June 29, 2026 19:44
Show Gist options
  • Select an option

  • Save bryanprimus/9bed1b6681a841c3bec0ad467e0db82f to your computer and use it in GitHub Desktop.

Select an option

Save bryanprimus/9bed1b6681a841c3bec0ad467e0db82f to your computer and use it in GitHub Desktop.
drizzle-orm 0.45.2 pnpm patch — types only: a single-object insert + .returning() infers [Row] (non-empty tuple) instead of Row[], so destructuring gives Row, not Row | undefined under noUncheckedIndexedAccess. Arrays, insert-select, and onConflict stay Row[]. No runtime change.
diff --git a/pg-core/query-builders/insert.d.cts b/pg-core/query-builders/insert.d.cts
index 87005b57215f0865efcd6da620e8d63fd7b97572..649f43ab2990848e70fd8f7ec7ed3a8c11c1c8f9 100644
--- a/pg-core/query-builders/insert.d.cts
+++ b/pg-core/query-builders/insert.d.cts
@@ -48,16 +48,23 @@ export declare class PgInsertBuilder<TTable extends PgTable, TQueryResult extend
constructor(table: TTable, session: PgSession, dialect: PgDialect, withList?: Subquery[] | undefined, overridingSystemValue_?: boolean | undefined);
private authToken?;
overridingSystemValue(): Omit<PgInsertBuilder<TTable, TQueryResult, true>, 'overridingSystemValue'>;
- values(value: PgInsertValue<TTable, OverrideT>): PgInsertBase<TTable, TQueryResult>;
- values(values: PgInsertValue<TTable, OverrideT>[]): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: (qb: QueryBuilder) => PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: (qb: QueryBuilder) => SQL): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: SQL): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult>;
+ values(value: PgInsertValue<TTable, OverrideT>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'one'>;
+ values(values: PgInsertValue<TTable, OverrideT>[]): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: (qb: QueryBuilder) => PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: (qb: QueryBuilder) => SQL): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: SQL): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
}
-export type PgInsertWithout<T extends AnyPgInsert, TDynamic extends boolean, K extends keyof T & string> = TDynamic extends true ? T : Omit<PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['selectedFields'], T['_']['returning'], TDynamic, T['_']['excludedMethods'] | K>, T['_']['excludedMethods'] | K>;
-export type PgInsertReturning<T extends AnyPgInsert, TDynamic extends boolean, TSelectedFields extends SelectedFieldsFlat> = PgInsertBase<T['_']['table'], T['_']['queryResult'], TSelectedFields, SelectResultFields<TSelectedFields>, TDynamic, T['_']['excludedMethods']>;
-export type PgInsertReturningAll<T extends AnyPgInsert, TDynamic extends boolean> = PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['table']['_']['columns'], T['_']['table']['$inferSelect'], TDynamic, T['_']['excludedMethods']>;
+/**
+ * Local patch: tracks INSERT cardinality at the type level only (no runtime effect).
+ * `'one'` means `.values(singleObject)` was used, so `.returning()` resolves to a
+ * non-empty tuple `[Row]`; `'many'`/`'unknown'` keep the original `Row[]` shape.
+ */
+export type PgInsertCardinality = 'one' | 'many' | 'unknown';
+export type PgInsertResult<TQueryResult extends PgQueryResultHKT, TReturning extends Record<string, unknown> | undefined, TCardinality extends PgInsertCardinality> = TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TCardinality extends 'one' ? [TReturning] : TReturning[];
+export type PgInsertWithout<T extends AnyPgInsert, TDynamic extends boolean, K extends keyof T & string, TCardinality extends PgInsertCardinality = T['_']['cardinality']> = TDynamic extends true ? T : Omit<PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['selectedFields'], T['_']['returning'], TDynamic, T['_']['excludedMethods'] | K, TCardinality>, T['_']['excludedMethods'] | K>;
+export type PgInsertReturning<T extends AnyPgInsert, TDynamic extends boolean, TSelectedFields extends SelectedFieldsFlat> = PgInsertBase<T['_']['table'], T['_']['queryResult'], TSelectedFields, SelectResultFields<TSelectedFields>, TDynamic, T['_']['excludedMethods'], T['_']['cardinality']>;
+export type PgInsertReturningAll<T extends AnyPgInsert, TDynamic extends boolean> = PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['table']['_']['columns'], T['_']['table']['$inferSelect'], TDynamic, T['_']['excludedMethods'], T['_']['cardinality']>;
export interface PgInsertOnConflictDoUpdateConfig<T extends AnyPgInsert> {
target: IndexColumn | IndexColumn[];
/** @deprecated use either `targetWhere` or `setWhere` */
@@ -67,12 +74,12 @@ export interface PgInsertOnConflictDoUpdateConfig<T extends AnyPgInsert> {
set: PgUpdateSetSource<T['_']['table']>;
}
export type PgInsertPrepare<T extends AnyPgInsert> = PgPreparedQuery<PreparedQueryConfig & {
- execute: T['_']['returning'] extends undefined ? PgQueryResultKind<T['_']['queryResult'], never> : T['_']['returning'][];
+ execute: PgInsertResult<T['_']['queryResult'], T['_']['returning'], T['_']['cardinality']>;
}>;
export type PgInsertDynamic<T extends AnyPgInsert> = PgInsert<T['_']['table'], T['_']['queryResult'], T['_']['returning']>;
-export type AnyPgInsert = PgInsertBase<any, any, any, any, any, any>;
+export type AnyPgInsert = PgInsertBase<any, any, any, any, any, any, any>;
export type PgInsert<TTable extends PgTable = PgTable, TQueryResult extends PgQueryResultHKT = PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = ColumnsSelection | undefined, TReturning extends Record<string, unknown> | undefined = Record<string, unknown> | undefined> = PgInsertBase<TTable, TQueryResult, TSelectedFields, TReturning, true, never>;
-export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never> extends TypedQueryBuilder<TSelectedFields, TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'>, SQLWrapper {
+export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never, TCardinality extends PgInsertCardinality = 'many'> extends TypedQueryBuilder<TSelectedFields, PgInsertResult<TQueryResult, TReturning, TCardinality>>, QueryPromise<PgInsertResult<TQueryResult, TReturning, TCardinality>>, RunnableQuery<PgInsertResult<TQueryResult, TReturning, TCardinality>, 'pg'>, SQLWrapper {
readonly _: {
readonly dialect: 'pg';
readonly table: TTable;
@@ -81,10 +88,11 @@ export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQue
readonly returning: TReturning;
readonly dynamic: TDynamic;
readonly excludedMethods: TExcludedMethods;
- readonly result: TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[];
+ readonly cardinality: TCardinality;
+ readonly result: PgInsertResult<TQueryResult, TReturning, TCardinality>;
};
}
-export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never> extends QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]> implements TypedQueryBuilder<TSelectedFields, TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'>, SQLWrapper {
+export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never, TCardinality extends PgInsertCardinality = 'many'> extends QueryPromise<PgInsertResult<TQueryResult, TReturning, TCardinality>> implements TypedQueryBuilder<TSelectedFields, PgInsertResult<TQueryResult, TReturning, TCardinality>>, RunnableQuery<PgInsertResult<TQueryResult, TReturning, TCardinality>, 'pg'>, SQLWrapper {
private session;
private dialect;
static readonly [entityKind]: string;
@@ -138,7 +146,7 @@ export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends P
onConflictDoNothing(config?: {
target?: IndexColumn | IndexColumn[];
where?: SQL;
- }): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'>;
+ }): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate', 'many'>;
/**
* Adds an `on conflict do update` clause to the query.
*
@@ -168,7 +176,7 @@ export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends P
* });
* ```
*/
- onConflictDoUpdate(config: PgInsertOnConflictDoUpdateConfig<this>): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'>;
+ onConflictDoUpdate(config: PgInsertOnConflictDoUpdateConfig<this>): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate', 'many'>;
toSQL(): Query;
prepare(name: string): PgInsertPrepare<this>;
private authToken?;
diff --git a/pg-core/query-builders/insert.d.ts b/pg-core/query-builders/insert.d.ts
index c869db58c707cedd0a7c782cde74f1fa3a24af23..cf9f11483c2c06de1022a80b5dc0a8e3462bd6b8 100644
--- a/pg-core/query-builders/insert.d.ts
+++ b/pg-core/query-builders/insert.d.ts
@@ -48,16 +48,23 @@ export declare class PgInsertBuilder<TTable extends PgTable, TQueryResult extend
constructor(table: TTable, session: PgSession, dialect: PgDialect, withList?: Subquery[] | undefined, overridingSystemValue_?: boolean | undefined);
private authToken?;
overridingSystemValue(): Omit<PgInsertBuilder<TTable, TQueryResult, true>, 'overridingSystemValue'>;
- values(value: PgInsertValue<TTable, OverrideT>): PgInsertBase<TTable, TQueryResult>;
- values(values: PgInsertValue<TTable, OverrideT>[]): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: (qb: QueryBuilder) => PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: (qb: QueryBuilder) => SQL): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: SQL): PgInsertBase<TTable, TQueryResult>;
- select(selectQuery: PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult>;
+ values(value: PgInsertValue<TTable, OverrideT>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'one'>;
+ values(values: PgInsertValue<TTable, OverrideT>[]): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: (qb: QueryBuilder) => PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: (qb: QueryBuilder) => SQL): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: SQL): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
+ select(selectQuery: PgInsertSelectQueryBuilder<TTable>): PgInsertBase<TTable, TQueryResult, undefined, undefined, false, never, 'many'>;
}
-export type PgInsertWithout<T extends AnyPgInsert, TDynamic extends boolean, K extends keyof T & string> = TDynamic extends true ? T : Omit<PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['selectedFields'], T['_']['returning'], TDynamic, T['_']['excludedMethods'] | K>, T['_']['excludedMethods'] | K>;
-export type PgInsertReturning<T extends AnyPgInsert, TDynamic extends boolean, TSelectedFields extends SelectedFieldsFlat> = PgInsertBase<T['_']['table'], T['_']['queryResult'], TSelectedFields, SelectResultFields<TSelectedFields>, TDynamic, T['_']['excludedMethods']>;
-export type PgInsertReturningAll<T extends AnyPgInsert, TDynamic extends boolean> = PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['table']['_']['columns'], T['_']['table']['$inferSelect'], TDynamic, T['_']['excludedMethods']>;
+/**
+ * Local patch: tracks INSERT cardinality at the type level only (no runtime effect).
+ * `'one'` means `.values(singleObject)` was used, so `.returning()` resolves to a
+ * non-empty tuple `[Row]`; `'many'`/`'unknown'` keep the original `Row[]` shape.
+ */
+export type PgInsertCardinality = 'one' | 'many' | 'unknown';
+export type PgInsertResult<TQueryResult extends PgQueryResultHKT, TReturning extends Record<string, unknown> | undefined, TCardinality extends PgInsertCardinality> = TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TCardinality extends 'one' ? [TReturning] : TReturning[];
+export type PgInsertWithout<T extends AnyPgInsert, TDynamic extends boolean, K extends keyof T & string, TCardinality extends PgInsertCardinality = T['_']['cardinality']> = TDynamic extends true ? T : Omit<PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['selectedFields'], T['_']['returning'], TDynamic, T['_']['excludedMethods'] | K, TCardinality>, T['_']['excludedMethods'] | K>;
+export type PgInsertReturning<T extends AnyPgInsert, TDynamic extends boolean, TSelectedFields extends SelectedFieldsFlat> = PgInsertBase<T['_']['table'], T['_']['queryResult'], TSelectedFields, SelectResultFields<TSelectedFields>, TDynamic, T['_']['excludedMethods'], T['_']['cardinality']>;
+export type PgInsertReturningAll<T extends AnyPgInsert, TDynamic extends boolean> = PgInsertBase<T['_']['table'], T['_']['queryResult'], T['_']['table']['_']['columns'], T['_']['table']['$inferSelect'], TDynamic, T['_']['excludedMethods'], T['_']['cardinality']>;
export interface PgInsertOnConflictDoUpdateConfig<T extends AnyPgInsert> {
target: IndexColumn | IndexColumn[];
/** @deprecated use either `targetWhere` or `setWhere` */
@@ -67,12 +74,12 @@ export interface PgInsertOnConflictDoUpdateConfig<T extends AnyPgInsert> {
set: PgUpdateSetSource<T['_']['table']>;
}
export type PgInsertPrepare<T extends AnyPgInsert> = PgPreparedQuery<PreparedQueryConfig & {
- execute: T['_']['returning'] extends undefined ? PgQueryResultKind<T['_']['queryResult'], never> : T['_']['returning'][];
+ execute: PgInsertResult<T['_']['queryResult'], T['_']['returning'], T['_']['cardinality']>;
}>;
export type PgInsertDynamic<T extends AnyPgInsert> = PgInsert<T['_']['table'], T['_']['queryResult'], T['_']['returning']>;
-export type AnyPgInsert = PgInsertBase<any, any, any, any, any, any>;
+export type AnyPgInsert = PgInsertBase<any, any, any, any, any, any, any>;
export type PgInsert<TTable extends PgTable = PgTable, TQueryResult extends PgQueryResultHKT = PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = ColumnsSelection | undefined, TReturning extends Record<string, unknown> | undefined = Record<string, unknown> | undefined> = PgInsertBase<TTable, TQueryResult, TSelectedFields, TReturning, true, never>;
-export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never> extends TypedQueryBuilder<TSelectedFields, TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'>, SQLWrapper {
+export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never, TCardinality extends PgInsertCardinality = 'many'> extends TypedQueryBuilder<TSelectedFields, PgInsertResult<TQueryResult, TReturning, TCardinality>>, QueryPromise<PgInsertResult<TQueryResult, TReturning, TCardinality>>, RunnableQuery<PgInsertResult<TQueryResult, TReturning, TCardinality>, 'pg'>, SQLWrapper {
readonly _: {
readonly dialect: 'pg';
readonly table: TTable;
@@ -81,10 +88,11 @@ export interface PgInsertBase<TTable extends PgTable, TQueryResult extends PgQue
readonly returning: TReturning;
readonly dynamic: TDynamic;
readonly excludedMethods: TExcludedMethods;
- readonly result: TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[];
+ readonly cardinality: TCardinality;
+ readonly result: PgInsertResult<TQueryResult, TReturning, TCardinality>;
};
}
-export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never> extends QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]> implements TypedQueryBuilder<TSelectedFields, TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]>, RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'>, SQLWrapper {
+export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends PgQueryResultHKT, TSelectedFields extends ColumnsSelection | undefined = undefined, TReturning extends Record<string, unknown> | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never, TCardinality extends PgInsertCardinality = 'many'> extends QueryPromise<PgInsertResult<TQueryResult, TReturning, TCardinality>> implements TypedQueryBuilder<TSelectedFields, PgInsertResult<TQueryResult, TReturning, TCardinality>>, RunnableQuery<PgInsertResult<TQueryResult, TReturning, TCardinality>, 'pg'>, SQLWrapper {
private session;
private dialect;
static readonly [entityKind]: string;
@@ -138,7 +146,7 @@ export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends P
onConflictDoNothing(config?: {
target?: IndexColumn | IndexColumn[];
where?: SQL;
- }): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'>;
+ }): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate', 'many'>;
/**
* Adds an `on conflict do update` clause to the query.
*
@@ -168,7 +176,7 @@ export declare class PgInsertBase<TTable extends PgTable, TQueryResult extends P
* });
* ```
*/
- onConflictDoUpdate(config: PgInsertOnConflictDoUpdateConfig<this>): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'>;
+ onConflictDoUpdate(config: PgInsertOnConflictDoUpdateConfig<this>): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate', 'many'>;
toSQL(): Query;
prepare(name: string): PgInsertPrepare<this>;
private authToken?;
@bryanprimus

Copy link
Copy Markdown
Author

Scenarios covered

/**
 * Type-level proof for the local drizzle-orm patch (see patches/drizzle-orm@*.patch).
 *
 * This file is type-checked by `pnpm typecheck` (tsc --noEmit) and never executed.
 * Each `Expect<Equal<...>>` line fails to compile if the inferred type is wrong, so a
 * clean typecheck is the proof that the patched insert types behave as intended under
 * `noUncheckedIndexedAccess`.
 */
import { sql } from 'drizzle-orm'

import { db } from '@/db'
import { domains } from '@/domains/schema'

type Expect<T extends true> = T
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false

type Row = typeof domains.$inferSelect

const baseValues = {
  id: 'd_1',
  organizationId: 'org_1',
  name: 'example.com',
  region: 'us-east-1',
  dkimSelector: 'sel',
  dkimPublicKey: 'pub',
  provisioningStatus: 'provisioning',
} as const

async function proof() {
  // Rule 1: values(singleObject).returning() infers a non-empty tuple [Row]
  const single = await db.insert(domains).values(baseValues).returning()
  type _single = Expect<Equal<typeof single, [Row]>>

  // Destructuring a single insert yields Row, NOT Row | undefined
  const [singleRow] = await db.insert(domains).values(baseValues).returning()
  type _singleRow = Expect<Equal<typeof singleRow, Row>>

  // Rule 2: values(array).returning() still infers Row[]
  const many = await db.insert(domains).values([baseValues]).returning()
  type _many = Expect<Equal<typeof many, Row[]>>

  // Rule 3: insert ... select still infers Row[]
  const fromSelect = await db.insert(domains).select(sql`select * from ${domains}`).returning()
  type _fromSelect = Expect<Equal<typeof fromSelect, Row[]>>

  // Rule 4: onConflictDoNothing().returning() downgrades to Row[]
  const conflict = await db.insert(domains).values(baseValues).onConflictDoNothing().returning()
  type _conflict = Expect<Equal<typeof conflict, Row[]>>

  // Rule 5: onConflictDoUpdate().returning() downgrades to Row[]
  const upsert = await db
    .insert(domains)
    .values(baseValues)
    .onConflictDoUpdate({ target: domains.id, set: { name: 'updated' } })
    .returning()
  type _upsert = Expect<Equal<typeof upsert, Row[]>>

  // Partial returning on a single insert is also a single-element tuple
  const singleId = await db.insert(domains).values(baseValues).returning({ id: domains.id })
  type _singleId = Expect<Equal<typeof singleId, [{ id: string }]>>

  // Partial returning on a bulk insert stays an array
  const manyIds = await db.insert(domains).values([baseValues]).returning({ id: domains.id })
  type _manyIds = Expect<Equal<typeof manyIds, { id: string }[]>>

  // No returning() is unchanged: a driver query result, not Row[]
  const noReturning = await db.insert(domains).values(baseValues)
  type _noReturning = Expect<Equal<[typeof noReturning] extends [Row[]] ? true : false, false>>

  void single
  void singleRow
  void many
  void fromSelect
  void conflict
  void upsert
  void singleId
  void manyIds
  void noReturning

  return null as unknown as [
    _single,
    _singleRow,
    _many,
    _fromSelect,
    _conflict,
    _upsert,
    _singleId,
    _manyIds,
    _noReturning,
  ]
}

void proof

to test

run

npx tsc --noEmit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment