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

在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后的数据类型

  1. 新建接口描述populate后的Tag结构,覆盖createdBy的类型:
// 只保留User中被select的字段,更贴合实际返回数据
interface TagDocumentPopulated extends Omit<TagDocument, 'createdBy'> {
  createdBy: Pick<UserDocument, 'uniqueAddress'>;
}
  1. 在查询结果中添加类型断言,告诉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类型

  1. 先导入PopulateDoc类型:
import mongoose, { Document, Model, PopulateDoc } from 'mongoose';
  1. 修改TagDocument接口,让createdBy同时支持ObjectId和populate后的User类型:
interface TagDocument extends Document {
  name: string;
  content: Array<mongoose.Types.ObjectId>;
  createdBy: PopulateDoc<mongoose.Types.ObjectId | UserDocument>;
  synced: boolean;
}
  1. (可选)如果不需要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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:01:14