trpc-rest

Query Parameters

How query parameters are parsed and coerced from strings to their expected types.

For GET and DELETE endpoints, input comes from URL query parameters. Since query params are always strings, the handler automatically coerces them to match your Zod schema types.

Supported coercions

Zod typeQuery stringCoerced value
z.number()?count=4242
z.boolean()?active=truetrue
z.boolean()?active=0false
z.bigint()?id=90071992547409939007199254740993n
z.date()?after=2024-01-01T00:00:00ZDate object
z.array(z.number())?ids=1&ids=2[1, 2]
z.string()?name=alice'alice' (no coercion)

Array handling

Single query values are automatically wrapped into arrays when the schema expects an array:

// Schema
z.object({ tags: z.array(z.string()) })

// ?tags=alpha → { tags: ['alpha'] }
// ?tags=a&tags=b → { tags: ['a', 'b'] }

Array elements are individually coerced:

// Schema
z.object({ ids: z.array(z.number()) })

// ?ids=1&ids=2&ids=3 → { ids: [1, 2, 3] }

Optional and default values

Optional and default fields work as expected:

z.object({
  page: z.number().default(1),
  size: z.number().default(20),
  active: z.boolean().optional(),
})

// No query params → validated as {} → defaults applied by Zod
// ?page=5 → { page: 5 } → size defaults to 20

Schema safety

Coercion never mutates your Zod schemas. The handler creates new objects with coerced values and passes them through Zod validation. Invalid values (e.g. ?count=abc for a number field) are left as strings and caught by Zod validation, returning a BAD_REQUEST error.

On this page