Drizzle Type Reference

Every public TypeScript type exported by @evensurface/paginate-drizzle.

These types come from @evensurface/paginate-drizzle and describe the query builders, options, ordering configuration, and errors used by the Drizzle adapter.

import type {
  DrizzlePaginationOptions,
  DrizzleCursorOrder,
  DrizzleCursorPaginationOptions,
} from "@evensurface/paginate-drizzle"

Type parameters: TItem is one row produced by your Drizzle .select() query. For example, if your query selects { id: users.id, name: users.name }, then TItem is { id: number; name: string }.

Page and offset query types

DrizzleSelectQuery

interface DrizzleSelectQuery<TItem> {
  limit(limit: number): DrizzleLimitedQuery<TItem>
}

The type of a select builder before a limit is applied. The Drizzle adapter calls .limit(limit) on it. This interface describes only the methods Paginate needs; a real Drizzle builder can have many more methods.

DrizzleLimitedQuery

interface DrizzleLimitedQuery<TItem> {
  offset(offset: number): PromiseLike<TItem[]>
}

The builder after .limit() has been applied. The adapter calls .offset(offset), awaits the result, and receives an array of TItem rows. PromiseLike<TItem[]> means the object can be awaited like a Promise.

DrizzleSelectQueryFactory

type DrizzleSelectQueryFactory<TItem> = () => DrizzleSelectQuery<TItem>

A function that creates a new select query whenever Paginate needs to fetch. It receives no arguments.

const query = () => db.select().from(users).orderBy(asc(users.id))

The db, users, and asc names in that example are from your Drizzle application, not exports from Paginate. Fresh builders matter because the adapter applies .limit() and .offset() to them and rejects reuse of the same builder.

DrizzleCountRow

interface DrizzleCountRow {
  total: number
}

One row from a select({ total: count() }) query. Its total field must be a non-negative safe integer.

DrizzleCountResult

type DrizzleCountResult = number | readonly DrizzleCountRow[]

The two count result shapes that the adapter supports:

  • A number, such as 95, usually from db.$count().
  • A read-only array containing exactly one { total: number } row, such as [{ total: 95 }], from a select count query.

An empty array or an array with two or more rows is invalid. So are negative, fractional, or unsafe count values.

DrizzleCountQuery

type DrizzleCountQuery = PromiseLike<DrizzleCountResult>

An awaitable Drizzle count query. Pass the query itself to countQuery; the adapter awaits it when the pagination operation starts. This is not a callback or factory like the select query.

Page and offset option types

DrizzlePaginationOptions

interface DrizzlePaginationOptions<TItem> {
  query: DrizzleSelectQueryFactory<TItem>
  countQuery: DrizzleCountQuery
  page?: PaginationInput
  limit?: PaginationInput
  pageSizeOptions?: PageSizeOptions
}

Passed to paginate() from @evensurface/paginate-drizzle.

FieldRequired?Meaning
queryYesFunction that builds a new select query, including application filters and stable ordering.
countQueryYesAwaitable total count for the same filters.
pageNoOne-based page; defaults to 1.
limitNoRows per page; defaults to 20 (normally capped at 100).
pageSizeOptionsNoCustom page-size policy.

PaginationInput and PageSizeOptions are exported from the core package. The output is PaginatedResult<TItem>.

DrizzleOffsetPaginationOptions

interface DrizzleOffsetPaginationOptions<TItem> {
  query: DrizzleSelectQueryFactory<TItem>
  countQuery: DrizzleCountQuery
  offset?: PaginationInput
  limit?: PaginationInput
  pageSizeOptions?: PageSizeOptions
}

Passed to paginateOffset() from @evensurface/paginate-drizzle. It works like DrizzlePaginationOptions, but takes offset instead of page.

FieldRequired?Meaning
queryYesFactory creating a new select query for the fetch.
countQueryYesAwaitable count of matching rows.
offsetNoZero-based number of rows to skip. Defaults to 0 and is preserved past the end.
limitNoMaximum rows returned; defaults to 20.
pageSizeOptionsNoOptional limit policy.

The output is OffsetPaginatedResult<TItem>.

Cursor query types

Cursor mode does not need a count query or numeric offset.

DrizzleCursorSelectQuery

interface DrizzleCursorSelectQuery<TItem> {
  limit(limit: number): PromiseLike<TItem[]>
}

A cursor select builder that is ready for a limit. The adapter applies .limit(requestedLimit + 1) and awaits the rows. It does not call .offset().

DrizzleCursorQueryOptions

interface DrizzleCursorQueryOptions {
  cursorWhere: SQL | undefined
  orderBy: readonly SQL[]
}

The argument passed to your cursor query factory by the adapter. SQL is the expression type from drizzle-orm.

FieldTypeMeaning
cursorWhereSQL | undefinedA Drizzle condition that selects only rows after the cursor. undefined on the first request.
orderByreadonly SQL[]Generated ascending/descending order expressions to pass into .orderBy(...orderBy).

You must combine cursorWhere with your own filters using .where(and(yourFilter, cursorWhere)), and apply the provided orderBy. The adapter cannot check whether you actually used both inside your callback.

DrizzleCursorQueryFactory

type DrizzleCursorQueryFactory<TItem> = (
  options: DrizzleCursorQueryOptions,
) => DrizzleCursorSelectQuery<TItem>

A callback that accepts the generated cursor condition and ordering expressions, then returns a fresh Drizzle select builder. Unlike the page/offset factory, it receives an argument.

const query = ({ cursorWhere, orderBy }: DrizzleCursorQueryOptions) =>
  db.select().from(users).where(cursorWhere).orderBy(...orderBy)

That example only shows the callback shape. Add your own filters and access checks to real queries. See the complete Drizzle guide.

DrizzleCursorValueType

type DrizzleCursorValueType = "string" | "number" | "bigint" | "date"

The runtime representation of an ordering column. Drizzle's built-in column types generally provide this information, but custom columns require valueType to tell the adapter how to validate and serialize their values.

DrizzleCursorOrderEntry

This type describes one ordering key. Its public type is a union that ties the column's data type to the return type of getValue().

The following definition includes its internal helper so you can see the exact type constraints:

import type { AnyColumn } from "drizzle-orm"

type DrizzleCursorValueType = "string" | "number" | "bigint" | "date"

type DrizzleCursorOrderEntryBase = {
  key: string
  direction: "asc" | "desc"
}

type DrizzleCursorOrderEntryForValue<
  TItem,
  TValue extends string | number | bigint | Date,
  TValueType extends DrizzleCursorValueType,
> = DrizzleCursorOrderEntryBase &
  (
    | {
        column: AnyColumn<{ data: TValue; dataType: TValueType; notNull: true }>
        valueType?: TValueType
        getValue(item: TItem): TValue
      }
    | {
        column: AnyColumn<{ data: TValue; dataType: "custom"; notNull: true }>
        valueType: TValueType
        getValue(item: TItem): TValue
      }
  )

export type DrizzleCursorOrderEntry<TItem> =
  | DrizzleCursorOrderEntryForValue<TItem, string, "string">
  | DrizzleCursorOrderEntryForValue<TItem, number, "number">
  | DrizzleCursorOrderEntryForValue<TItem, bigint, "bigint">
  | DrizzleCursorOrderEntryForValue<TItem, Date, "date">

This shows the effective public constraints; DrizzleCursorOrderEntryBase and DrizzleCursorOrderEntryForValue are explanatory/internal names, not separate package exports.

FieldTypeMeaning
keystringStable name stored in the cursor, such as "createdAt". No duplicate names allowed.
direction"asc" | "desc"Direction for this column.
columnAnyColumn<...>A non-null Drizzle column, used in the keyset SQL predicate.
valueTypeDrizzleCursorValueTypeUsually optional for built-in columns; required for custom columns.
getValue(item)(item: TItem) => TValueReads that column's value from a selected result row. Must return the matching runtime type.

Example for an ordinary integer ID column:

{
  key: "id",
  column: users.id,
  direction: "asc",
  getValue: (row) => row.id,
}

For a custom column that returns strings, add valueType: "string" to tell the adapter how to interpret it. The adapter rejects nullable order columns, duplicate keys, invalid values, and cursors whose keys/types don't match the configured order.

DrizzleCursorOrder

type DrizzleCursorOrder<TItem> = readonly [
  DrizzleCursorOrderEntry<TItem>,
  ...DrizzleCursorOrderEntry<TItem>[],
]

A non-empty, read-only list of cursor ordering entries. Usually the final entry is a unique, immutable ID so that two rows never have the exact same ordering tuple.

Example: createdAt DESC, id DESC. See Drizzle Cursor Pagination for a full usage example.

DrizzleCursorPaginationOptions

interface DrizzleCursorPaginationOptions<TItem> {
  query: DrizzleCursorQueryFactory<TItem>
  orderBy: DrizzleCursorOrder<TItem>
  cursor?: string
  limit?: PaginationInput
  pageSizeOptions?: PageSizeOptions
}

Passed to the Drizzle paginateCursor() function.

FieldRequired?Meaning
queryYesCallback receiving generated SQL cursor conditions and ordering expressions.
orderByYesColumn ordering configuration used to build predicates and cursors.
cursorNoPrevious nextCursor token; omit for the first request.
limitNoMaximum rows returned (adapter fetches one extra).
pageSizeOptionsNoCustom default/minimum/maximum limit policy.

It returns CursorPaginatedResult<TItem>. query must create a fresh builder on each call.

Drizzle error types

DrizzlePaginationError

A native RangeError or TypeError with a read-only code, depending on the error. It is defined as a union (shown here with its code subsets):

type DrizzlePaginationError =
  | (RangeError & {
      readonly code: "DRIZZLE_INVALID_COUNT_ROWS" | "DRIZZLE_INVALID_COUNT"
    })
  | (TypeError & {
      readonly code:
        | "DRIZZLE_QUERY_REUSED"
        | "DRIZZLE_INVALID_CURSOR_ORDER"
        | "DRIZZLE_CURSOR_ORDER_MISMATCH"
    })

Use isDrizzlePaginationError(error) to safely identify and narrow these errors. The underlying implementation derives the union from its error-code definitions.

DrizzlePaginationErrorCode

This type is a union of all Drizzle-specific error codes:

type DrizzlePaginationErrorCode =
  | "DRIZZLE_INVALID_COUNT_ROWS"
  | "DRIZZLE_INVALID_COUNT"
  | "DRIZZLE_QUERY_REUSED"
  | "DRIZZLE_INVALID_CURSOR_ORDER"
  | "DRIZZLE_CURSOR_ORDER_MISMATCH"

For exact causes and handling examples, see Errors.


Want the shared pagination types, like PaginationMetadata, CursorPosition, or PageSizeOptions? Visit the Core Type Reference.

On this page