Skip to Content
ControllerVovkRequest Type

VovkRequest Type

The request object accepted by controller methods is represented by the VovkRequest type. It extends Next.js’s NextRequest by parameterizing input body, query, and params (see below). Use it to strongly type built‑in request methods like req.json() and req.nextUrl.searchParams, which are otherwise typed as any and string | null.

import { put, type VovkRequest } from 'vovk'; export default class UserController { @put('{id}') static async updateUser(req: VovkRequest<{ foo: 'foo' }, { bar: 'bar' }>, { id }: { id: string }) { const data = await req.json(); // data type is { foo: 'foo' } const bar = req.nextUrl.searchParams.get('bar'); // bar type is 'bar' // ... } }

Validation libraries define the request type themselves, so you usually don’t need to use VovkRequest manually.

The second argument of the handler method defines the type of parameters extracted from the request URL.

req.vovk

To avoid modifying the original NextRequest object, Vovk introduces the req.vovk object, which contains additional utilities for request processing. Validation libraries (like vovk-dto) can override these functions to return a different type.

async req.vovk.body()

The req.vovk.body function returns the request body parsed as an object. In most cases, it behaves the same as req.json().

import { post, type VovkRequest } from 'vovk'; export default class UserController { @post() static async createUser(req: VovkRequest<{ foo: string }>) { const body = await req.vovk.body(); // body type is { foo: string } // ... } }

req.vovk.query()

The req.vovk.query function returns typed query parameters.

import { get, type VovkRequest } from 'vovk'; export default class UserController { @get() static async getUser(req: VovkRequest<null, { id: string }>) { const query = req.vovk.query(); // query type is { id: string } // ... } }

Nested Queries

Nested data is serialized as a query string with square brackets, commonly referred to as “PHP‑style” or “bracket notation”.

  • Square brackets [ ] denote keys for arrays or nested objects.
  • Sequential numeric indices (e.g., [0], [1]) represent array elements.
  • Named keys (e.g., [f], [u]) represent object properties.
  • The structure can be nested arbitrarily to represent complex data.

The following query string:

?simple=value&array[0]=first&array[1]=second&object[key]=value&nested[obj][prop]=data&nested[arr][0]=item1&nested[arr][1]=item2&complex[items][0][name]=product&complex[items][0][price]=9.99&complex[items][0][tags][0]=new&complex[items][0][tags][1]=featured

Is parsed as:

{ simple: "value", array: ["first", "second"], object: { key: "value" }, nested: { obj: { prop: "data" }, arr: ["item1", "item2"] }, complex: { items: [ { name: "product", price: "9.99", tags: ["new", "featured"] } ] } }

req.vovk.params()

The req.vovk.params function returns typed route parameters. To type it properly, use the third generic argument of VovkRequest.

import { get, type VovkRequest } from 'vovk'; export default class UserController { @get('{id}') static async getUser(req: VovkRequest<null, null, { id: string }>) { const params = req.vovk.params(); // params type is { id: string } // ... } }

async req.vovk.form()

The req.vovk.form function returns the request FormData serialized into an object. It’s a type‑safe alternative to req.formData() that reads form data and uses Object.fromEntries(formData.entries()) to convert it into a plain object. The generic argument defines the shape of the form data.

interface Data { foo: string; bar: string; file: File; } const formDataObject = await req.vovk.form<Data>(); // the same as // const body = await req.formData(); // const formDataObject = Object.fromEntries(body.entries()) as Data;

When validation libraries are used with the isForm option, req.vovk.form is typed automatically—no generic is required.

req.vovk.meta()

The req.vovk.meta function gets and sets request metadata. If an argument is provided, it merges into the existing metadata and returns the current value. To type the metadata, pass a generic type.

interface RequestMeta { foo: string; bar: string; currentUser: User; } // set foo and bar meta information req.vovk.meta<RequestMeta>({ foo: 'foo', bar: 'bar' }); // set currentUser meta information req.vovk.meta<RequestMeta>({ currentUser: user }); // get meta information const meta = req.vovk.meta<RequestMeta>(); // meta type is RequestMeta including foo, bar, and currentUser

The metadata is usually set in a custom decorator and read in the controller method. Read more in the meta documentation.

Last updated on