We use cookies to enhance your experience on the site
CodeWorlds

DTO Documentation - Seals on Parchment

Every document in the imperial chancellery had to have precisely described fields - the petitioner's name, the type of matter, the date, and the seal. In NestJS, the equivalent of these documents are DTOs (Data Transfer Objects), and the

@ApiProperty()
decorator describes each field so that Swagger UI can display it.

@ApiProperty - Basics

The

@ApiProperty()
decorator describes a single field in a DTO class:

1import { ApiProperty } from '@nestjs/swagger';
2
3export class CreateLegionaryDto {
4  @ApiProperty({
5    description: 'Name of the legionary',
6    example: 'Marcus Aurelius',
7  })
8  name: string;
9
10  @ApiProperty({
11    description: 'Rank in the legion',
12    example: 'Centurio',
13  })
14  rank: string;
15
16  @ApiProperty({
17    description: 'Years of experience',
18    example: 5,
19    minimum: 0,
20    maximum: 40,
21  })
22  experience: number;
23}

@ApiProperty Options

The decorator accepts many configuration options:

| Option | Description | Example | |--------|-------------|---------| |

description
| Field description |
'Name of the legionary'
| |
example
| Example value |
'Marcus'
| |
required
| Whether the field is required |
true
/
false
| |
default
| Default value |
'Miles'
| |
enum
| List of allowed values |
['Centurio', 'Miles']
| |
type
| Field type |
String
,
Number
,
Boolean
| |
isArray
| Whether the field is an array |
true
| |
minimum
| Minimum value (number) |
0
| |
maximum
| Maximum value (number) |
100
| |
minLength
| Minimum length (string) |
2
| |
maxLength
| Maximum length (string) |
50
|

Optional Fields with @ApiPropertyOptional

For optional fields, we use

@ApiPropertyOptional()
:

1import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2
3export class UpdateLegionaryDto {
4  @ApiPropertyOptional({
5    description: 'New rank of the legionary',
6    example: 'Optio',
7  })
8  rank?: string;
9
10  @ApiPropertyOptional({
11    description: 'New assigned legion',
12    example: 'Legio III Augusta',
13  })
14  legio?: string;
15
16  @ApiPropertyOptional({
17    description: 'Additional experience',
18    example: 2,
19    minimum: 0,
20  })
21  additionalExperience?: number;
22}

Fields with enum - Legion Ranks

Enum is particularly useful for fields with a limited set of values:

1export enum LegionaryRank {
2  MILES = 'Miles',
3  OPTIO = 'Optio',
4  CENTURIO = 'Centurio',
5  TRIBUNUS = 'Tribunus',
6  LEGATUS = 'Legatus',
7}
8
9export class CreateLegionaryDto {
10  @ApiProperty({
11    description: 'Rank of the legionary',
12    enum: LegionaryRank,
13    example: LegionaryRank.MILES,
14  })
15  rank: LegionaryRank;
16}

Nested Objects - Legion Structure

For nested DTOs, we use the

type
option:

1export class AddressDto {
2  @ApiProperty({ description: 'Province name', example: 'Pannonia' })
3  province: string;
4
5  @ApiProperty({ description: 'City name', example: 'Aquincum' })
6  city: string;
7}
8
9export class LegionDto {
10  @ApiProperty({ description: 'Legion name', example: 'Legio X Gemina' })
11  name: string;
12
13  @ApiProperty({
14    description: 'Legion location',
15    type: AddressDto,
16  })
17  location: AddressDto;
18
19  @ApiProperty({
20    description: 'List of centurions',
21    type: [String],
22    example: ['Marcus', 'Julius', 'Gaius'],
23  })
24  centurions: string[];
25}

Response DTOs

It is a good practice to create separate DTOs for API responses:

1export class LegionaryResponseDto {
2  @ApiProperty({ description: 'Legionary ID', example: '507f1f77bcf86cd799439011' })
3  id: string;
4
5  @ApiProperty({ description: 'Name of the legionary', example: 'Marcus Aurelius' })
6  name: string;
7
8  @ApiProperty({ description: 'Rank', enum: LegionaryRank })
9  rank: LegionaryRank;
10
11  @ApiProperty({ description: 'Recruitment date', example: '2024-01-15T10:30:00Z' })
12  recruitedAt: Date;
13
14  @ApiProperty({ description: 'Is active', example: true })
15  isActive: boolean;
16}

Practical Exercise

Create DTO documentation for the Empire's province management system:

Go to CodeWorlds