You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中如何管理接口、模型与验证类?解决冗余代码痛点

NestJS 减少DTO、Mongoose Schema与接口重复代码的实践

问题背景

我在新项目中使用NestJS,被大量样板代码困扰,尤其是DTO类、Mongoose Schema和接口的编写。之前的流程是:先定义描述集合文档字段的接口,再编写实现该接口的DTO验证类,还要编写与接口镜像的Mongoose Schema(最初以为Schema无法直接实现接口,后来修正了这一认知)。这种方式导致修改文档结构时需要在三处同步更新,并且Schema与DTO存在重复的验证逻辑。

我有以下疑问:

  • 能否完全舍弃DTO类,仅用接口和Schema,在插入数据库时完成验证?
  • 若不可行,有没有无需修改三处代码的替代方案?用DTO类替代接口是否可行?

最优实践方案

我已找到适合自身场景的最优方案,分享给遇到同类问题的开发者:

核心思路是:先定义描述模型的接口,使用@nestjs/mongoose的@Schema装饰器编写Schema类并实现该接口,同时保留实现同一接口的DTO用于请求验证。

针对特殊字段的处理规则:

  • 若存在创建时无需传入但需存入数据库的字段,在接口中将其设为可选类型,DTO实现时直接忽略该字段;
  • 若后续需要编辑这类字段,则将其添加到更新DTO中。

方案优势:修改接口时,DTO和Schema会通过类型检查报错提醒更新;多数项目中数据库迁移并不频繁,接口还能在代码其他场景复用。虽然仍需更新三个文件,但每个文件职责明确,是目前最优雅的解决方案。

代码示例

1. 定义模型接口

import { EventFormat } from '../enums';

interface IEvent {
  eventId: string;
  name: string;
  rank: number;
  format: EventFormat;
}

export default IEvent;

2. 编写Mongoose Schema类

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import IEvent from '~/shared_helpers/interfaces/Event';
import { EventFormat } from '~/shared_helpers/enums';

@Schema({ timestamps: true })
export class Event implements IEvent {
  @Prop({ required: true, immutable: true, unique: true })
  eventId: string;

  @Prop({ required: true })
  name: string;

  @Prop({ required: true })
  rank: number;

  @Prop({ enum: EventFormat, required: true })
  format: EventFormat;
}

// 数据库查询的返回类型
export type EventDocument = HydratedDocument<Event>;
// 用于依赖注入的Schema实例
export const EventSchema = SchemaFactory.createForClass(Event);

3. 编写DTO类

创建事件DTO
import { IsEnum, IsNumber, IsString, Min, MinLength } from 'class-validator';
import IEvent from '~/shared_helpers/interfaces/Event';
import { EventFormat } from '~/shared_helpers/enums';

export class CreateEventDto implements IEvent {
  @IsString()
  @MinLength(3)
  eventId: string;

  @IsString()
  @MinLength(3)
  name: string;

  @IsNumber()
  @Min(0)
  rank: number;

  @IsEnum(EventFormat)
  format: EventFormat;
}
更新事件DTO
import { PartialType } from '@nestjs/mapped-types';
import { CreateEventDto } from './create-event.dto';

export class UpdateEventDto extends PartialType(CreateEventDto) {
  // 如果接口中有创建时不需要传入的可选字段,
  // 若需要支持编辑,可在此处添加对应的验证逻辑
}

内容的提问来源于stack exchange,提问作者CodeToCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 04:20:22