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 的验证会读取用装饰器编写的规则,而装饰器需要类。这就是下一课的内容。
挑战
简单客户端现在可以创建已完成的任务。使用 DTO 描述 POST /tasks 的请求体。DTO 是一个列出请求体所含字段的类,并将它一路传递给服务。
- 在
src/tasks/dto/create-task.dto.ts中,为类CreateTaskDto添加两个字段:title,类型为字符串;以及done,类型为可选的布尔值。 - 在
src/tasks/tasks.controller.ts中,修改create方法。它的@Body()参数现在的类型是CreateTaskDto,而不是{ title: string }。将整个 DTO 传给服务,而不只是传递标题。 - 在
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 {}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
TypeScript 和 NestJS中的所有课
自己练习: Express 在线编辑器