在TypeScript的Mongoose Schema中使用ref报错:ObjectId无uniqueAddress属性
解决Mongoose Populate与TypeScript结合的类型错误
你的报错根源在于:TagDocument接口里createdBy被定义为mongoose.Types.ObjectId,但执行populate后该字段会被替换为UserDocument实例,TypeScript无法自动识别这种类型变化,因此抛出Property 'uniqueAddress' does not exist on type 'ObjectId'错误。以下是具体解决方法:
方法一:自定义Populate后的数据类型
- 新建接口描述populate后的Tag结构,覆盖
createdBy的类型:
// 只保留User中被select的字段,更贴合实际返回数据 interface TagDocumentPopulated extends Omit<TagDocument, 'createdBy'> { createdBy: Pick<UserDocument, 'uniqueAddress'>; }
- 在查询结果中添加类型断言,告诉TypeScript当前数据的实际类型:
export const getTagsToSync = async (): Promise<TagToSync[]> => { return Tag.find({ synced: false }) .populate({ path: 'createdBy', model: 'User', select: 'uniqueAddress' }) .then(tags => (tags as TagDocumentPopulated[]).map(tag => ({ name: tag.name, createdBy: tag.createdBy.uniqueAddress }))); }
方法二:使用Mongoose自带的PopulateDoc类型
- 先导入
PopulateDoc类型:
import mongoose, { Document, Model, PopulateDoc } from 'mongoose';
- 修改
TagDocument接口,让createdBy同时支持ObjectId和populate后的User类型:
interface TagDocument extends Document { name: string; content: Array<mongoose.Types.ObjectId>; createdBy: PopulateDoc<mongoose.Types.ObjectId | UserDocument>; synced: boolean; }
- (可选)如果不需要Mongoose文档实例,用
lean()返回普通JS对象,类型处理更直观:
export const getTagsToSync = async (): Promise<TagToSync[]> => { return Tag.find({ synced: false }) .populate({ path: 'createdBy', model: 'User', select: 'uniqueAddress' }) .lean() .then(tags => (tags as (Omit<TagDocument, 'createdBy'> & { createdBy: { uniqueAddress: string } })[]).map(tag => ({ name: tag.name, createdBy: tag.createdBy.uniqueAddress }))); }
内容的提问来源于stack exchange,提问作者fist ace
相关产品推荐
相关产品推荐

