@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
Acceptlines) becomestring[]on the parameter. Declare the field as an array type.
What gets coerced
| Declared type | Wire example | Coerces 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 absent | undefined |
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
- TypedBody β JSON request bodies.
- TypedQuery β query-string parameters.
- TypedParam β path parameters.
- Tutorial β Your First Endpoint β the broader pattern.
Last updated on