TypeScript中如何为MongoDB Mongoose自动生成字段定义正确类型
正确类型定义实现
类型错误根源为两点:
- 基础文档接口未声明
_id字段,导致Mongoose默认将其推导为可选属性 - 未区分「创建输入的可选字段」和「查询返回的必选字段」的类型边界,同时自定义的
FooOutput中_id为字符串类型,和Mongoose默认返回的ObjectId类型不匹配。
第一步:拆分字段类型定义
先将手动输入字段和自动生成字段拆分,方便复用:
import mongoose, { Model, Schema, Types } from "mongoose"; // 业务手动输入字段 interface FooBase { label: string; } // Mongoose自动生成字段 interface FooAutoFields { _id: Types.ObjectId; archived: boolean; created_at: number; updated_at: number; } // 完整文档类型(用于Schema和模型声明) export type Foo = FooBase & FooAutoFields; // 创建输入类型:仅保留需要手动传入的字段 export type FooInput = Omit<Foo, keyof FooAutoFields>; // 查询/创建返回类型:如果需要_id为字符串,可以在此处做类型转换 export type FooOutput = Omit<Foo, '_id'> & { _id: string };
第二步:修正Schema与模型声明
保持原有的Schema配置不变,泛型直接传入完整的Foo类型即可:
const FooSchema = new Schema<Foo, Model<Foo>>( { label: { type: String, required: true }, archived: { type: Boolean, default: false }, }, { timestamps: { createdAt: "created_at", updatedAt: "updated_at", currentTime: () => Date.now() / 1000, }, } ); const FooModel: Model<Foo> = mongoose.model<Foo>("Foo", FooSchema);
第三步:修正创建方法的类型处理
因为create方法默认返回的是Mongoose文档实例,需要调用toJSON()/toObject()转换为纯对象,同时将_id转为字符串匹配FooOutput类型:
export const createFoo = async (foo: FooInput): Promise<FooOutput> => { const doc = await FooModel.create(foo); const raw = doc.toJSON(); // 转换_id为字符串 return { ...raw, _id: raw._id.toString() }; };
额外说明
- 如果查询时使用
.lean()方法直接返回纯对象,可以直接用FooOutput作为返回类型,不需要额外转换实例:export const getFooById = async (id: string): Promise<FooOutput | null> => { const raw = await FooModel.findById(id).lean<Foo>(); if (!raw) return null; return { ...raw, _id: raw._id.toString() }; }; - 如果你不需要将
_id转为字符串,直接保留ObjectId类型,只需要把FooOutput的_id声明为Types.ObjectId即可,省去转换步骤。
内容的提问来源于stack exchange,提问作者rattray
相关产品推荐
相关产品推荐

