Nest+TypeScript中MongoDB未定义_id时如何使用findById?
问题
MongoDB 创建文档时会自动生成键为_id的 ObjectId 字段,即便模型中未显式定义_id: ObjectId,该字段仍会自动存在。但在 TypeScript 环境下直接访问文档的_id字段时会触发类型错误,比如在 NestJS 项目中调用findById方法时,TS 提示:
属性“_id”在类型“Package”上不存在。ts(2339)
示例模型代码:
@ObjectType("Package") @InputType("PackageInput") @Schema() export class Package { @Field(() => String) @Prop({ type: String }) status: PackageStatusesEnums; @Field(() => String) @Prop() statusReason: string; @Prop({ type: Object }) dimensions: PackageDimensions; @Field(() => String) @Prop() notes: string; }
调用代码:
const pckgRes = await this.findById(pckg._id)
解决方案
1. 显式定义_id字段
这是最直接的方案,在模型中添加_id字段并配置 Mongoose 装饰器,既让 TypeScript 识别该字段,又保留 MongoDB 自动生成值的特性:
import { ObjectId } from 'mongoose'; @ObjectType("Package") @InputType("PackageInput") @Schema() export class Package { @Field(() => String) @Prop({ type: ObjectId, auto: true }) // auto: true 确保Mongo自动生成值 _id: ObjectId; // ... 其他原有字段 }
2. 继承 Mongoose 的Document类型
让模型类继承 Mongoose 内置的Document类型,该类型已包含_id、createdAt、updatedAt等 MongoDB 文档的默认属性:
import { Document } from 'mongoose'; @ObjectType("Package") @InputType("PackageInput") @Schema() export class Package extends Document { // ... 原有字段定义 }
继承后 TypeScript 会自动识别所有内置文档属性。
3. 临时使用类型断言
如果不想修改模型结构,可以通过类型断言跳过 TypeScript 的类型检查,适合临时场景:
// 方式1:精准断言 const pckgRes = await this.findById((pckg as unknown as { _id: string })._id); // 方式2:简化断言 const pckgRes = await this.findById((pckg as any)._id);
注意:这种方式会丢失类型检查的优势,不推荐长期使用。
4. 自定义基础文档类
如果多个模型都需要_id这类通用字段,可以创建一个基础类统一管理,避免重复代码:
import { ObjectId } from 'mongoose'; import { Field, ObjectType } from '@nestjs/graphql'; @ObjectType() export class BaseDocument { @Field(() => String) @Prop({ type: ObjectId, auto: true }) _id: ObjectId; } // 让Package类继承基础类 @ObjectType("Package") @InputType("PackageInput") @Schema() export class Package extends BaseDocument { // ... 原有字段定义 }
内容的提问来源于stack exchange,提问作者m3.b
相关产品推荐
相关产品推荐

