Mongoose 7.3.x 的已填充文档接口

huangapple go评论58阅读模式
英文:

Interface for populated docs mongoose 7.3.x

问题

让我们假设我有以下模型 User

import { Schema, model, Types, HydratedDocument } from "mongoose";

interface IUser {
  _id: Types.ObjectId;
  name: string;
  parent: Types.ObjectId;
}

interface IUserPopulate {
  parent: IUser;
}

type MergePopulate<I, IP> = Omit<HydratedDocument<I>, keyof IP> & IP;

const UserSchema = new Schema<IUser>({
  name: String,
  parent: { type: Schema.Types.ObjectId, ref: "users" },
});

const UserModel = model("users", UserSchema);

然后,我使用 UserModel#find 方法来查找用户:

async function getUser() {
  const users = await UserModel.find().populate<IUserPopulate>("parent");
  users.forEach((user) => {
    processUser(user);
  });
}

并且 processUser 函数接受已经填充的用户文档:

async function processUser(user: MergePopulate<IUser, IUserPopulate>) {
  // 做一些事情
}

TypeScript 可以接受使用 find() 方法查找的用户文档,但如果我使用 findOnefindById,TypeScript 就无法接受。

const user = await UserModel.findOne().populate<IUserPopulate>("parent");

processUser(user); // 这里会引发很多错误

我如何为这两种查询定义接口?

请注意,这在 mongoose 版本低于 7 时是有效的,但当我升级到 7.3.0 版本时出现了这个错误。

中文翻译结束,以下是代码部分,无需翻译。

英文:

Let's say I have model User like bellow

import { Schema, model, Types, HydratedDocument } from &quot;mongoose&quot;;

interface IUser {
  _id: Types.ObjectId;
  name: string;
  parent: Types.ObjectId;
}

interface IUserPopulate {
  parent: IUser;
}

type MergePopulate&lt;I, IP&gt; = Omit&lt;HydratedDocument&lt;I&gt;, keyof IP&gt; &amp; IP;

const UserSchema = new Schema&lt;IUser&gt;({
  name: String,
  parent: { type: Schema.Types.ObjectId, ref: &quot;users&quot; },
});

const UserModel = model(&quot;users&quot;, UserSchema);

then I find users by the method UserModel#find

async function getUser() {
  const users = await UserModel.find().populate&lt;IUserPopulate&gt;(&quot;parent&quot;);
  users.forEach((user) =&gt; {
    processUser(user);
  });
}

and function process user accepts populated user's docs

async function processUser(user: MergePopulate&lt;IUser, IUserPopulate&gt;) {
//do some thing
}

Typescript accept user docs when I use find() but don't accept if I use findOne or findById

const user = await UserModel.findOne().populate&lt;IUserPopulate&gt;(&quot;parent&quot;);

processUser(user); //throw alot of error here

How can I define Interface for both query?

Note It's work for mongoose < 7, I just got this error when upgrade mongoose to 7.3.0

答案1

得分: 1

findOnefindById 返回一个文档或 null,因此您必须添加一个测试来排除它们返回 null 的情况:

const user = await UserModel.findOne().populate<IUserPopulate>("parent");
if (user) {
  processUser(user);
}

Playground

英文:

findOne and findById return a document or null, so you must add a test to eliminate the case where they return null:

const user = await UserModel.findOne().populate&lt;IUserPopulate&gt;(&quot;parent&quot;);
if(user) {
  processUser(user);
}

Playground

答案2

得分: 0

找到了

```typescript
type MergePopulate<I, IP> = Omit<Document<unknown, {}, I & {
    _id: Types.ObjectId
  }> & Omit<I & {
    _id: Types.ObjectId
  } & Required<{
    _id: Types.ObjectId
  }>>, keyof IP> & IP

然后我可以使用合并填充文档的接口


<details>
<summary>英文:</summary>

Found it

```typescript
type MergePopulate&lt;I, IP&gt; = Omit&lt;Document&lt;unknown, {}, I &amp; {
    _id: Types.ObjectId
  }&gt; &amp; Omit&lt;I &amp; {
    _id: Types.ObjectId
  } &amp; Required&lt;{
    _id: Types.ObjectId
  }&gt;, never&gt;, keyof IP&gt; &amp; IP

And then I can use interface of merge populate for populated docs

huangapple
  • 本文由 发表于 2023年7月10日 15:57:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76651762.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定