Skip to main content

Decorators Overview

What are decorators?​

Decorators in express-cargo annotate class fields to tell the middleware:

  • Where to extract data from (e.g., body, query)
  • How to validate it
  • How to transform it

When you pass a class to bindingCargo, the middleware reads these decorators to build, validate, and transform a type-safe object that you retrieve with getCargo.

Decorator Categories​

Decorators are grouped by the role they play in the binding pipeline.

CategoryPurposeExamplesReference
SourceChoose where a field's value comes from@Body, @Query, @Header, @Uri / @Params, @Session, @UploadedFile, @UploadedFilesSource Decorators, File Upload Decorators
RequestRead a value straight from the Express Request@RequestVirtual Field Decorators
VirtualCompute a field from the other fields of the object@VirtualVirtual Field Decorators
TransformModify a single field's value before binding@TransformTransformation Decorator
Type helperDecide how a raw value is interpreted and cast@Type, @List, @EnumType Helper Decorators
ValidationEnforce rules on a field's value@Min, @Max, @Email, @OneOf, …Validation Decorators
Missing-valueDecide what happens when a field is absent@Default, @OptionalHandling Missing Fields

Source, Request, and Virtual answer the same question — where does this field come from? — so every field must carry exactly one of them, and they cannot be mixed. @UploadedFile and @UploadedFiles are source decorators that read the multipart parser's output, which is why @UploadedFile and @Body on one field are rejected the same way @Body and @Query are.

For the deeper @Type and @List scenarios — polymorphism, circular references, arrays of custom classes — see Type Transformation & Polymorphism and List Decorator under Advanced Usage.

Stacking Decorators​

A single field can carry decorators from multiple categories. They are read together to bind, transform, and validate that field:

import { Body, Transform, MinLength } from 'express-cargo'

class CreateUserRequest {
@Body('email') // Source: read from req.body.email
@Transform((value: string) => value.trim()) // Transform: normalize the value
@MinLength(5) // Validation: enforce a rule
email!: string
}

Stacking is limited within a category rather than across categories: a field takes one source, one type helper, and one missing-value strategy, while validation decorators can be stacked freely. bindingCargo() checks these rules when the route is registered and throws CargoSchemaError before the server handles a request.

Each category is documented in its own page linked above.