Mongoose返回文档的TypeScript函数返回类型错误如何解决?
Mongoose + TypeScript 查询函数返回类型定义错误解决
问题场景
项目中使用Mongoose编写查询函数返回模型文档,迁移到TypeScript时,定义返回类型遇到以下问题:
Box模型代码
import mongoose, { Schema, Types } from 'mongoose'; export interface Box { name: string set: Types.ObjectId } const BoxSchema = new Schema({ name: { type: String, unique: true, required: true, dropDups: true }, set: { type: Schema.Types.ObjectId, ref: 'Set', required: true } }); const Box = mongoose.model<Box>('Box', BoxSchema); export default Box;
原始控制器代码
import Box from '../models/Box'; static async getAllBoxes () { return await Box.find({}).exec(); }
尝试按照IDE提示定义返回类型后,抛出错误:
'Box' refers to a value, but is being used as a type here. Did you mean 'typeof Box'?
改为typeof Box后,又出现类型不匹配错误:
Type '(Document<unknown, any, Box> & Box & { _id: ObjectId; })[]' is not assignable to type '(Document<unknown, any, Model<Box, {}, {}, {}, any>> & Model<Box, {}, {}, {}, any> & { id: ObjectId; })[]'.
解决方案
方法1:自定义文档类型(通用兼容方案)
在Box模型文件中,明确导出Mongoose文档实例类型(即数据库返回的 hydrated 文档类型,包含_id、save()等Mongoose内置属性和方法):
import mongoose, { Schema, Types, Document } from 'mongoose'; export interface Box { name: string set: Types.ObjectId } // 定义文档类型:合并自定义接口与Mongoose Document属性 export type BoxDocument = Document<unknown, any, Box> & Box & { _id: Types.ObjectId; }; const BoxSchema = new Schema({ name: { type: String, unique: true, required: true, dropDups: true }, set: { type: Schema.Types.ObjectId, ref: 'Set', required: true } }); // 创建模型时使用自定义文档类型 const Box = mongoose.model<BoxDocument>('Box', BoxSchema); export default Box;
然后在控制器中直接使用该类型:
import Box, { BoxDocument } from '../models/Box'; static async getAllBoxes(): Promise<BoxDocument[]> { return await Box.find({}).exec(); }
方法2:使用Mongoose官方HydratedDocument类型(Mongoose 6.0+)
Mongoose 6.0及以上版本提供了HydratedDocument类型,可直接生成文档实例类型,无需手动定义:
在控制器中导入并使用:
import Box, { Box } from '../models/Box'; import { HydratedDocument } from 'mongoose'; static async getAllBoxes(): Promise<HydratedDocument<Box>[]> { return await Box.find({}).exec(); }
错误原因说明
- 直接使用
Box作为类型时,Box是默认导出的模型实例(值),而非TypeScript类型,因此报错。 - 使用
typeof Box得到的是模型类的类型,不是数据库返回的文档实例类型,导致类型不匹配。 - 正确的做法是使用Mongoose提供的文档实例类型(自定义
BoxDocument或官方HydratedDocument),这类类型会合并自定义接口与Mongoose内置的文档属性,与查询返回值的类型完全匹配。
内容的提问来源于stack exchange,提问作者Daniel Corona
相关产品推荐
相关产品推荐

