Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>'

Posted

技术标签:

【中文标题】Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>\'【英文标题】:Mongoose TypeScript ObjectId casting - Type 'string' is not assignable to type 'Condition<ObjectId | undefined>'Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>' 【发布时间】:2021-11-23 11:10:58 【问题描述】:

当我通过 ObjectId 字段进行查询时,我遇到了 mongoose 查询问题。传递mongoose.Types.ObjectIdstring 都会引发错误。只有当我将 ObjectId 转换为 mongoose.Schema.Types.ObjectId 时,TypeScript 才会停止抱怨,然后它会在运行时崩溃,因为它不是有效的 ObjectId。

interface DocumentWithTimestamp extends Document<ObjectId> 
  createdAt: Date;
  updatedAt: Date;

首先,我注意到 Document 将 _id 定义为 ObjectId | undefined,这已经使一切复杂化了。

我将我的模式定义如下:

export interface LanguageSchema extends DocumentWithTimestamp 
  langCode: string;
  locale: string;



interface LanguageModel extends Model<LanguageSchema> 
  mapToLanguage(language: LeanDocument<LanguageSchema> | LanguageSchema): Language;


const languageSchema = new Schema<LanguageSchema, LanguageModel>(
  
    langCode:  type: String, required: true, trim: true ,
    locale:  type: String, unique: true, required: true, trim: true ,
  ,
   collection: 'language', timestamps: true, versionKey: false ,
);

languageSchema.statics.mapToLanguage = function (language: LeanDocument<LanguageSchema> | LanguageSchema): Language 
  return 
    id: language._id?.toString() || '', // why is _id conditional...?
    langCode: language.langCode,
    locale: language.locale,
  ;
;

export const LanguageModel = model<LanguageSchema, LanguageModel>('Language', languageSchema);

现在通过 _id 或任何其他 ObjectId 字段查询我的 LanguageModel 会引发类型错误:

export async function findLanguagesByIds(languageIds: string[]) 
  return LanguageModel.find( _id:  $in: languageIds  ).lean();

错误:

Argument of type ' _id:  $in: string[]; ; ' is not assignable to parameter of type 'Callback<LanguageSchema[]>'.
      Object literal may only specify known properties, and '_id' does not exist in type 'Callback<LanguageSchema[]>'.

当我尝试将 string[] 转换为 Schema.Types.ObjectId[] 数组时,错误消失了,但这不是解决方案,因为它在运行时崩溃(Schema.Types.ObjectId 不是有效的 ObjectId)。

const languages = await LanguageModel.find(
  _id:  $in: languageIds.map((id) => new mongoose.Schema.Types.ObjectId(id)) ,
).lean();

如果我转换为 mongoose.Types.ObjectId(转换为真正的 ObjectId),它会再次引发错误...

感谢任何帮助!

【问题讨论】:

【参考方案1】:

我找到了解决问题的方法。

mongoose 文件定义如下:

class Document<T = any, TQueryHelpers = any, DocType = any> 
  constructor(doc?: any);

  /** This documents _id. */
  _id?: T;

  // ...
  

我使用Document&lt;ObjectId&gt; 对其进行了扩展。然而,ObjectId 类型是 Schema 类型,例如

import  ObjectId  from "mongoose";

但它实际上应该是猫鼬的实际 ObjectId 类型而不是 Schema 类型!

修复:

import  Types  from "mongoose"

interface DocumentWithTimestamp extends Document<Types.ObjectId> 
  createdAt: Date;
  updatedAt: Date;

【讨论】:

这里来自 mongoose 的超级令人困惑的 api.... 他们需要更好的支持。甚至不知道为什么你必须定义一个模型和一个接口......巨大的痛苦

以上是关于Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>'的主要内容,如果未能解决你的问题,请参考以下文章

typescript 使用TypeScript和MongoDb的Mongoose示例

typescript 使用TypeScript和MongoDb的Mongoose示例

typescript 使用TypeScript和MongoDb的Mongoose示例

Mongoose 的 loadClass() 和 TypeScript

graphql + mongoose + typescript,如何减少重复的模型定义

带有 Typescript 的 Mongoose Schema - 设计错误