乐闻世界logo
搜索文章和话题

NestJS 为什么同时需要使用 dto 和 interface?

3个答案

1
2
3

NestJS在设计模式上提倡使用Data Transfer Objects(DTOs)和接口(Interfaces)来实现应用程序逻辑的分离以及类型安全。

1. DTOs(Data Transfer Objects)

DTOs在NestJS中通常用于定义数据的传输格式。它们是用来约束客户端发送到服务器端的数据结构,确保数据的一致性和验证。DTOs通常带有装饰器(decorators),这些装饰器可以提供验证规则,确保只有符合这些规则的数据才被接受和处理。

例子:

假设我们有一个创建用户的API,我们可能会定义一个CreateUserDto类,来确保我们接收到的数据包含usernamepassword,并且它们都是字符串:

typescript
import { IsString } from 'class-validator'; export class CreateUserDto { @IsString() readonly username: string; @IsString() readonly password: string; }

在上面的例子中,class-validator库提供了@IsString()装饰器来验证传入数据的类型。

2. 接口(Interfaces)

接口在TypeScript和NestJS中用于定义对象的结构,它们是为了编译时的类型检查而存在。接口定义了对象可以有哪些属性以及这些属性的类型。它们不会编译到JavaScript中,因此不会在运行时提供任何的验证。

例子:

在服务或者模块之间共享数据结构时,我们可以定义一个接口来约定数据的形状。

typescript
interface User { id: number; username: string; password: string; }

在上述例子中,User接口描述了用户对象必须包含的属性和类型。任何实现了User接口的对象都必须有idusernamepassword这三个属性。

为什么同时需要?

使用DTOs和接口结合起来可以带来以下优势:

  • 分层的数据验证:DTOs可以在应用层对传入的数据进行严格的验证,而接口则在编译时提供类型检查,确保代码的正确性。
  • 代码可维护性:接口提供了一个清晰的契约定义,可以被服务、控制器和其他类实现,这使得代码更加模块化和可维护。
  • 灵活性和扩展性:DTOs可以为特定的操作定义数据格式,例如创建、更新,而接口则定义了应用程序级别的数据模型。这两者的结合使得扩展和重构变得更加容易。
  • 隔离变化:如果来自外部的数据需求变化,通常只需要调整DTO,而不需要修改内部使用的接口,这样可以最小化变化对系统的影响。

综上所述,DTOs和接口共同为NestJS提供了一个灵活、可靠和可维护的数据处理框架。通过在编译时和运行时各自发挥作用,它们确保了类型安全和数据一致性,同时也提高了代码的可读性和维护性。

2024年6月29日 12:07 回复

我想DTO用最简单的例子来解释这个概念,以便您更好地理解。DTO 代表数据传输对象。现在,DTO 用于减少代码重复。它只是定义了一个模式,该模式在函数的参数中传递,以便轻松地从函数中获取所需的数据。这是一个例子DTO

shell
export class AuthCredentialsDto { email: string; password: string; }

现在如果我们制作一个方法来检查密码是否正确

shell
async password_check(usercredentials: AuthCredentialsDTO) { //Destructuring in JAVASCRIPT const {email} = usercredentials; //Database Logic to find the email return user; }

现在,如果我们不使用 DTO,那么代码将如下所示

shell
async password_check(email: string, password: string) { //Database Logic to find the email return user; }

另外一点是,这只是一个函数,在一个框架中,多个函数调用多个其他函数,需要一次又一次地传递参数。假设一个函数需要 10 个参数。你必须多次通过它们。尽管可以在没有 a 的情况下工作DTO,但这不是一种开发友好的做法。一旦习惯了,DTO您就会喜欢使用它们,因为它们节省了大量额外的代码和精力。

2024年6月29日 12:07 回复

NestJS中使用DTO和Interface的原因

基本上,在 REST API 中,我们有两种类型的操作,一种是输入,另一种是输出。这是请求响应

在响应期间,我们不需要验证返回值。我们只需要根据接口传递数据即可

但根据请求,我们需要验证正文

例如,您要创建一个用户。那么请求体可能是这样的

shell
const body = { name: "Test Name", email: "test@gmail.com", phone: "0393939", age: 25 }

因此,在请求期间,我们需要验证电子邮件电话号码密码是否与正则表达式等匹配。

所以在DTO中我们可以做所有的验证

这是我的 DTO 示例之一

shell
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator'; export class RegisterUserRequest { @IsString() @IsNotEmpty() name: string; @IsEmail() @IsNotEmpty() email: string; @IsNotEmpty() @MinLength(6) password: string; } export class LoginUserRequest { @IsEmail() @IsNotEmpty() email: string; @IsNotEmpty() @MinLength(6) password: string; }

这是界面示例

shell
import { UserRole } from './user.schema'; export interface UserType { _id?: string; email?: string; name?: string; role: UserRole; createdAt?: Date; updatedAt?: Date; }

2024年6月29日 12:07 回复

你的答案