Menu
CoddyTech

DTOs

本课属于 Coddy Node.js 学习旅程的“TypeScript 和 NestJS”单元。第 13 课,共 24 课。

@Body() body: { title: string } 只在一个地方描述了请求体,而且没有任何检查:{ "title": 42 } 会直接通过。DTO,即数据传输对象,是一个描述请求体内容的类。

export class CreateOrderDto {
    customer: string;
    express?: boolean;
}

@Post()
create(@Body() dto: CreateOrderDto) {
    return this.ordersService.create(dto);
}

express? 表示一个可选字段。控制器和服务共用这个类,因此它们对数据结构的理解一致。

DTO 使用类而不是接口是有原因的。代码运行时,接口会和其他类型一起被移除,而类仍然存在。Nest 的验证会读取用装饰器编写的规则,而装饰器需要类。这就是下一课的内容。

challenge icon

挑战

简单

客户端现在可以创建已完成的任务。使用 DTO 描述 POST /tasks 的请求体。DTO 是一个列出请求体所含字段的类,并将它一路传递给服务。

  1. 在 src/tasks/dto/create-task.dto.ts 中,为类 CreateTaskDto 添加两个字段:title,类型为字符串;以及 done,类型为可选的布尔值。
  2. 在 src/tasks/tasks.controller.ts 中,修改 create 方法。它的 @Body() 参数现在的类型是 CreateTaskDto,而不是 { title: string }。将整个 DTO 传给服务,而不只是传递标题。
  3. 在 src/tasks/tasks.service.ts 中,修改 create,让它接收 DTO,而不是标题。新任务的 title 和 done 都从 DTO 中获取;如果请求体中没有 done,则使用 false。id 和 createdAt 的处理方式保持不变。

试试看:向 /tasks 发送 POST 请求,请求体为 { "title": "Pay rent", "done": true }。你会得到 201 响应和新任务,该任务已完成:

{ "id": 4, "title": "Pay rent", "done": true, "createdAt": "2026-10-30T09:15:00.000Z" }

(createdAt 显示的是请求时间。)发送 POST 请求,请求体为 { "title": "Buy milk" }:得到 201 响应,且 "done": false。然后发送 POST 请求,请求体为 { "title": 42 }。你仍然会得到 201 响应,并且 "title": 42 已保存:DTO 目前只描述请求体,还不会进行任何检查。下一课会让 Nest 拒绝这个请求。

亲手试试

// 描述 POST /tasks 的请求体:包含标题;如果客户端发送了 done,也包含 done。
export class CreateTaskDto {}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

TypeScript 和 NestJS中的所有课

自己练习: Express 在线编辑器