[ ] Regression
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
I have some troubles to figure it out when to use an interface and when to use a DTO.
Would you mind to add some details about dtos and interfaces in the doc (when to use what... etc)
From the nestjs docs :
But first (if you use TypeScript), we need to determine the DTO (Data Transfer Object) schema. A DTO is an object that defines how the data will be sent over the network. We could determine the DTO schema by using TypeScript interfaces, or by simple classes. Surprisingly, we recommend using classes here. Why? Classes are part of the JavaScript ES6 standard, and therefore they represent plain functions. On the other hand, since TypeScript interfaces are removed during the transpilation, Nest can't refer to them. This is important because features such as Pipes enable additional possibilities when they have access to the metatype of the variable.
I read that, but I am not sure what it means. Is Nestjs suggesting the usage of DTO instead of interface in every case ?
In the other hand, I can find in the doc exemples mixing interfaces and dtos
@rlataguerra DTOs and interfaces are not two distinct things. DTOs can be implemented as either interfaces or classes, and the latter is clearly recommended by the documentation. Either way, you create DTOs that define the shape of data being sent or received - it's just a matter of preference how you actually define those.
it's just a matter of preference how you actually define those.
Not only preference, but also use case. Interfaces can not compute properties or use decorators, whereas classes can. NestJS recommends to use classes because you can add decorators from class-validator
to properties such as @IsString()
or @Max(20)
. With interfaces such a validation would only be possible outside of the interface context.
@BrunnerLivio has explained the main difference between DTOs and interfaces very well. Actually, this is the primary reason why classes are recommended in the ofc docs
thanks for clarifications 馃憤
@rlataguerra Thanks for posting the questions! Going through the documentation is confusing as the examples use both, even the github repo has the same. Can we improve documentation for new users to easily understand? Can we just use class throughout examples and at the end provide an alternate mentioning can be used as an interface.
who didn't understand what is DTO, and why it can be at same time Interface and Class,
Is not the documentation issue, you have troubles with understanding of OOP pattern,
In examples is presented as Interfaces and Class just for example, that if you just use it like a schema it's enough simple interface implementation,
But like is mention above, if you need more that simple representational schema, you can use Class that will be possible to tune in pipes and much more
Well that already exits by using
app.useGlobalPipes(
new ValidationPipe({
disableErrorMessages: false,
transform: true,
transformOptions: {
strategy: 'excludeAll'
}
}),
);
EDIT
Cooked up this to remove values form the request that are not in the DTO .. going to look at adding validation as well
import {ArgumentMetadata, Injectable, PipeTransform} from '@nestjs/common';
import {plainToClass} from 'class-transformer';
@Injectable()
export class SanitizePipe implements PipeTransform {
constructor(private readonly className: any) {
}
transform(value: any, metadata: ArgumentMetadata) {
return plainToClass(this.className, value, {excludeExtraneousValues:true}) as object as any;
}
}
import {ApiModelProperty} from '@nestjs/swagger';
import {Expose} from 'class-transformer';
export class CreateTopicDto {
@Expose()
@ApiModelProperty()
readonly title: string;
@Expose()
@ApiModelProperty()
readonly description: string;
}
md5-84c05d9810aaf80cdc1e35766d33c708
@Post()
@UsePipes(new SanitizePipe(CreateTopicDto))
@ApiOperation({title: 'Create Topic'})
async create(@Body() createTopicDto: CreateTopicDto) {
return await this.TopicsService.create(createTopicDto);
}
In our use case the DTO doesn't include properties that aren't already present in the entity, so we created an additional interface with the DTO parameters, which the DTO class as well as our entity class implements.
That way we have a 'single point of truth' as to which parameters need to be implemented by both. Maybe it's a bit overkill, but as I understood, typescript interfaces aren't compiled and are here to guide you while programming.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Not only preference, but also use case. Interfaces can not compute properties or use decorators, whereas classes can. NestJS recommends to use classes because you can add decorators from
class-validator
to properties such as@IsString()
or@Max(20)
. With interfaces such a validation would only be possible outside of the interface context.