Skip to Content

@TypedHeaders

@nestia/core
export function TypedHeaders(): ParameterDecorator;

Drop-in replacement for @Headers() from @nestjs/common. Behavior is identical plus:

  • Each declared header is validated against the declared TypeScript type.
  • Header values are coerced β€” "42" β†’ 42, "true" β†’ true, repeated headers β†’ string[].
  • A type mismatch returns 400 Bad Request.
  • The decorator is visible to @nestia/sdk β€” header schema appears in the generated SDK and Swagger document.

For auth tokens (Authorization header) and other identity carries, the typical NestJS pattern is a custom @User() decorator backed by a guard β€” not @TypedHeaders. Use this decorator for application-defined headers that carry data your handler needs: tenant codes, language preferences, custom x-… headers.


Basic usage

src/controllers/ArticlesController.ts
import { TypedHeaders, TypedRoute } from "@nestia/core"; import { Controller } from "@nestjs/common"; interface IRequestHeaders { "x-tenant": string; "x-locale"?: "en" | "ko" | "ja"; "x-version": number; } @Controller("articles") export class ArticlesController { @TypedRoute.Get() public async list( @TypedHeaders() headers: IRequestHeaders, ): Promise<IArticle[]> { const tenant = headers["x-tenant"]; const locale = headers["x-locale"] ?? "en"; // ... } }

A request without x-tenant returns 400. A request with x-version: abc returns 400. A request with valid headers calls the handler with the typed object.


Header-name conventions

  • Lowercase preferred. HTTP header names are case-insensitive on the wire, but Node normalizes them to lowercase. Declare "x-tenant", not "X-Tenant".
  • Uppercase tolerated. If the interface declares "X-Foo", Nestia matches it case-insensitively against the request β€” the value lands at the casing you declared.
  • Repeated headers (e.g. multiple Accept lines) become string[] on the parameter. Declare the field as an array type.

What gets coerced

Declared typeWire exampleCoerces to
string"foo""foo"
number"42"42
boolean"true" / "false"true / false
"a" | "b""a""a" (validated)
string[]repeated header["v1","v2"]
number[]comma-separated "1,2,3"[1, 2, 3]
Optional (?)header absentundefined

Tags layered on top (MinLength, Pattern, etc.) work the same as on body / query types.


When to use plain @Headers instead

Reach for the vanilla decorator when:

  • The header carries opaque data (Authorization: Bearer …) and you delegate parsing to a guard.
  • You need every header, not a known subset β€” declare the parameter as Record<string, string> with @Headers().

Vanilla @Headers() is invisible to @nestia/sdk’s generators.


See also

Last updated on