在TypeScript和NestS中将类转换为类/对象(实体到DTO)



如何转换数据库实体User

class User {
public firstName: string;
public lastName: string;
public phone?: string;
public email: string;
public status: EUserState;
public tokens: Token[];
public password: string;
}

进入 DTO 实体GetUserDTO

class GetUserDTO {
public id: number;
public firstName: string;
public lastName: string;
public phone?: string;
public email: string;
}

在打字稿中?我正在使用@nestjsclass-validatorclass-transformer包,但我没有找到任何方法来使用它们来实现这一点。

有人可能会说,拥有DTO毫无意义,但是我们在服务器和客户端之间共享DTO,以维护API结构。

有什么想法吗?

有几种方法可以实现您想要的

  1. 您可以使用DomainDTO中的static函数手动从Domain模型映射到DTOs
export class Domain {
...
static toDTO(domain: Domain) {
// mapping goes here
}
}

export class Dto {
...
static fromDomain(domain: Domain) {
// mapping goes here
}
}
  1. 您可以使用第三方库:automapper-ts@wufe/mapper@nartc/automapper(我的库(或morphism

class-transformer也可以被视为映射器,但是,如果您想从一个模型映射到另一个模型,那么class-transformer真的做不到。

我在很多项目中都使用以下方式:

共享文件夹(可以分离github存储库,monore lib,npm等(

// user-response.dto.ts
class UserResponseDto {
public readonly id: string;
// other dto fields...
// the simplest way is the same type as entity but the better one is to use own type (TUserData) instead
constructor(data: UserEntity) {
this.id = data.id;
}
}

后端:

// user.entity.ts
@Entity('users')
class UserEntity {
// your fields...
}
// users.controler.ts
// import { UserResponseDto } from '@shared';
@Controller('users')
class UsersController {
@Get()
public async getUsers(): Promise<UserResponseDto[]> {
const data = await this.service.getUsers();
return data.map(user => new UserResponseDto(user);
}
// Bonus: example of class-transform, class-validate
@Post()
@UsePipes(new ValidationPipe()) // you can use your own pipe, check: TransformPipe implements PipeTransform { ...implementation }
public async createUser(
@Body() dto: UserCreateDto,
): Promise<UserResponseDto> {}
}

前端取决于选择的方式,但概念是相同的:

// users.api.ts
// import { UserResponseDto } from '@shared';
usersApi = {
endpoints: {
getUsers: (): UserResponseDto[]
}
}

首先,通过使用类转换器的classToPlain将Entity更改为纯json

。然后,通过使用类转换器的普通到类将普通 json 更改为 DTO 像下面一样

public async getAll(): Promise<ItemDTO[]> {
return await this.repo.find()
.then(items => items.map(e=>plainToClass(ItemDTO, classToPlain(e), { excludeExtraneousValues: true })));
}

此外,让我们在 DTO 中使用 Exclude, Expose of class-transformer for for 客户端数据,以便客户端查看。

@Exclude()
export class ItemDTO implements Readonly<ItemDTO> {
@ApiProperty({ required: true })
@IsUUID()
@Expose()
id: string;
}

如果 DTO 来自数据库模型,则可以使用生成器工具从架构创建 DTO

。这个库是为从Prisma模式生成DTO和实体而制作的: https://github.com/robblovell/prisma-generator-nestjs/tree/main

它不会转换您的实体,但它可以为您工作

如果您不使用Prisma,也许还有其他一些库可以使用其他ORM,只是为了让您意识到这一点!

最新更新