【Nestjs学习日记】DTO

245 阅读4分钟

作者:markzzw 时间:2024-1-31

线上代码:CodeSandbox

Github:zhangzewei/nest-learning-tutorial

系列阅读

  1. 【Nestjs学习日记】初识nestjs
  2. 【Nestjs学习日记】Nest Controller
  3. 【Nestjs学习日记】抛出异常
  4. 【Nestjs学习日记】Module

在NestJS应用程序开发中,DTO(Data Transfer Object)是一个重要的概念。DTO用于在不同的层之间传输数据,并且在实现松耦合和数据验证方面发挥了关键的作用。在本篇【NestJS学习日记】中,我们将深入探讨DTO的概念和在NestJS应用程序中的应用。

在现代的应用程序开发中,经常会涉及到在不同的层之间传输数据。例如,从客户端发送的数据需要在服务器端进行处理和验证,然后可能会传递给数据库或其他外部服务。在这个过程中,数据的结构和格式可能会有所不同,这就是DTO的用武之地。

DTO是一种用于定义数据传输的对象,它定义了传输的数据的结构和字段。通过使用DTO,我们可以明确指定在不同层之间传输的数据的内容,确保数据的一致性和有效性。DTO还可以用于数据验证,以确保传输的数据符合预期的格式和规范。

在本篇【NestJS学习日记】中,我们将学习如何创建和使用DTO。我们将了解如何定义DTO类,如何在NestJS的控制器和服务中使用DTO,并且如何进行数据验证和转换。我们还将研究DTO的最佳实践和常见的使用场景。

通过理解和掌握DTO的概念和应用,我们将能够更好地组织和管理数据传输,在不同的层之间实现松耦合和有效的数据交互。DTO是NestJS应用程序开发中的重要概念,它能够提高代码的可读性、可维护性和可扩展性。

在接下来的文章中,让我们一起深入研究DTO的概念和应用,掌握在NestJS应用程序中使用DTO的技巧和技巧!

前期准备

这里需要先安装依赖

npm install class-validator
npm install class-transformer
npm install @nestjs/mapped-types

创建 DTO

在对应的 Module 目录下新建目录 ‘dto/’,然后新建 dto 文件,以 cat module 为例,新建 ‘cat.dto.ts’ 文件,然后在文件内部新增两个 dto 类。

export class CreateCatDto {
  name: string;
  age: number;
}

export class UpdateCatDto {
  name?: string;
  age?: number;
}

使用 DTO

Nestjs 是使用 Typescript 进行编写的,所以我们可以将这两个 dto 为 Controller 中的方法进行参数的类型描述。

cat.controller.ts

import { Controller, Body, Post, Param, Put } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto } from './dto/cat.dto';

@Controller('cat')
export class CatController {
  @Post()
  createCat(@Body() body: CreateCatDto) {
    return body;
  }

  @Put(':id')
  updateCat(@Param('id') id: string, @Body() body: UpdateCatDto) {
    return { id, body };
  }
}

使用 DTO 对参数校验

DTO 不仅仅是对参数进行类型描述,还可以对请求的参数进行类型校验,首先我们需要增加一个全局的校验 pipe。

app.module.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe()); // 新增校验 pipe
  await app.listen(3000);
}
bootstrap();

接下改变一下我们的 dto, 这里需要使用到 class-validator 提供的装饰器修饰 dto 类的属性。

import { IsString, IsNumber } from 'class-validator';

export class CreateCatDto {
  @IsString()
  name: string;
  @IsNumber()
  age: number;
}

此时我们尝试 post 请求:

  1. 不传入任何参数,返回了一个错误信息,告诉我们参数的要求。 image.png
  2. 传入 name 和 age,但是 age 给一个 string,此时只返回了对于 age 参数的描述。 image.png

这就是使用 dto 对参数进行校验的方法。

继承

可以看出 CreateDto 和 UpdateDto 是相似的,所以可以使用继承的方式,但是 UpdateCatDto 的属性是可选的,这就要使用 @nestjs/mapped-types 的 PartialType。

import { IsString, IsNumber } from 'class-validator';
import { PartialType } from '@nestjs/mapped-types';

export class CreateCatDto {
  @IsString()
  name: string;
  @IsNumber()
  age: number;
}

export class UpdateCatDto extends PartialType(CreateCatDto) {}

此时尝试 put 请求:

  1. 发出 name 和 age,没有报错。 image.png
  2. 只发出 name,没有报错。 image.png
  3. 只发出 age,但是是 string,报错 age 需要是数字类型。 image.png 可以看到 UpdateCatDto 即继承了 CreateDto 的校验,但是也有自身的可选类型描述。

总结

DTO 不仅可以帮助我们进行类型描述,还可以对 body 进行校验,并且通过继承可以把类似的类型组合起来,也不会失去校验的功能。