Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface vs DTO #1228

Closed
rlataguerra opened this issue Oct 24, 2018 · 11 comments
Closed

Interface vs DTO #1228

rlataguerra opened this issue Oct 24, 2018 · 11 comments

Comments

@rlataguerra
Copy link

[ ] 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)

@BrunnerLivio
Copy link
Member

BrunnerLivio commented Oct 24, 2018

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.

@rlataguerra
Copy link
Author

rlataguerra commented Oct 25, 2018

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

@skreborn
Copy link

@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.

@BrunnerLivio
Copy link
Member

BrunnerLivio commented Oct 25, 2018

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.

@kamilmysliwiec
Copy link
Member

@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

@rlataguerra
Copy link
Author

thanks for clarifications 👍

@sidzan
Copy link

sidzan commented Mar 18, 2019

@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.

@aspatari
Copy link

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

@ricardosaracino
Copy link

ricardosaracino commented Jun 21, 2019

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;
}
 @Post()
    @UsePipes(new SanitizePipe(CreateTopicDto))
    @ApiOperation({title: 'Create Topic'})
    async create(@Body() createTopicDto: CreateTopicDto) {
        return await this.TopicsService.create(createTopicDto);
    }

@bn326160
Copy link

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.

@lock
Copy link

lock bot commented Nov 20, 2019

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.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants