# Pagination

> Pagination request parameters and paginated response metadata.

- Name: `pagination`
- Categories: api
- Detail page: https://open-types.dev/types/pagination

## Install

```bash
# Types only
npx shadcn add @open-types/pagination

# Types + Zod v4 validators
npx shadcn add @open-types/pagination-zod

# Types + real-world examples
npx shadcn add @open-types/pagination-examples
```

## Types

```typescript
export type SortOrder = "asc" | "desc";

export interface Pagination {
  page?: number;
  pageSize?: number;
  sortBy?: string;
  sortOrder?: SortOrder;
}

export interface PaginationResponse {
  totalItems: number;
  totalPages: number;
  currentPage: number;
  pageSize: number;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
}
```

## Zod validator

```typescript
import * as z from "zod";
import type { Pagination, PaginationResponse, SortOrder } from "../types/pagination";

export const paginationSchema = z.object({
  page: z.number().int().min(1, { error: "Page must be at least 1" }).default(1),
  pageSize: z
    .number()
    .int()
    .min(1, { error: "Page size must be at least 1" })
    .max(100, { error: "Page size must be at most 100" })
    .default(20),
  sortBy: z.string().optional(),
  sortOrder: z.enum(["asc", "desc"]).default("asc").optional(),
}) satisfies z.ZodType<Pagination>;

export const paginationResponseSchema = z.object({
  totalItems: z.number().int().min(0),
  totalPages: z.number().int().min(0),
  currentPage: z.number().int().min(1),
  pageSize: z.number().int().min(1),
  hasNextPage: z.boolean(),
  hasPreviousPage: z.boolean(),
}) satisfies z.ZodType<PaginationResponse>;

export type { Pagination, PaginationResponse, SortOrder } from "../types/pagination";
```

## Examples

```typescript
// Source: hand-crafted
import type {
  SortOrder,
  Pagination,
  PaginationResponse,
} from "../types/pagination";

// SortOrder has no exported schema; values appear as a string union inside paginationSchema.
// Kept as a typed helper rather than a `*Examples` const so the fixture guard doesn't look
// for a non-existent sortOrderSchema.
export const sortOrderValues: readonly SortOrder[] = ["asc", "desc"];

export const paginationExamples = {
  empty: {} satisfies Pagination,
  firstPage: { page: 1, pageSize: 20 } satisfies Pagination,
  sorted: { page: 2, pageSize: 50, sortBy: "created_at", sortOrder: "desc" } satisfies Pagination,
  sortedAsc: { page: 1, pageSize: 100, sortBy: "name", sortOrder: "asc" } satisfies Pagination,
  maxPageSize: { page: 1, pageSize: 100 } satisfies Pagination,
} as const;

export const paginationResponseExamples = {
  middlePage: {
    totalItems: 482,
    totalPages: 25,
    currentPage: 5,
    pageSize: 20,
    hasNextPage: true,
    hasPreviousPage: true,
  } satisfies PaginationResponse,
  firstPage: {
    totalItems: 482,
    totalPages: 25,
    currentPage: 1,
    pageSize: 20,
    hasNextPage: true,
    hasPreviousPage: false,
  } satisfies PaginationResponse,
  lastPage: {
    totalItems: 482,
    totalPages: 25,
    currentPage: 25,
    pageSize: 20,
    hasNextPage: false,
    hasPreviousPage: true,
  } satisfies PaginationResponse,
  empty: {
    totalItems: 0,
    totalPages: 0,
    currentPage: 1,
    pageSize: 20,
    hasNextPage: false,
    hasPreviousPage: false,
  } satisfies PaginationResponse,
} as const;
```
