TypeScript - 如何结合使用猫鼬填充定义模型? [英] TypeScript - How to define model in combination with using mongoose populate?

查看:14
本文介绍了TypeScript - 如何结合使用猫鼬填充定义模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 Node.JS 应用程序中使用 mongoose 和 TypeScript.从数据库中获取数据时,我在很多地方使用了猫鼬的 populate.

I'm using mongoose and TypeScript in my Node.JS app. I'm using mongoose's populate in a bunch of places when fetching data from the database.

我面临的问题是我不知道如何键入我的模型,以便属性可以是 ObjectId 或填充来自另一个集合的数据.

The issue I'm facing is that I don't know how to type my models so that a property can be either an ObjectId or populated with data from another collection.

我尝试在我的模型类型定义中使用联合类型,这似乎是 TypeScript 提供的用于涵盖这些类型的内容:

I've attempted using union types in my model type definition, which seems like something that TypeScript offers to cover these kind of things:

interface User extends Document {
    _id: Types.ObjectId;
    name: string
}

interface Item extends Document {
    _id: Types.ObjectId;

    // Union typing here
    user: Types.ObjectId | User;
}

我的架构仅将属性定义为带有 ref 的 ObjectId.

My schema only defines the property as an ObjectId with ref.

const ItemSchema = new Schema({
    user: { type: Schema.Types.ObjectId, ref: "User", index: true }
})

示例:

所以我可能会这样做:

ItemModel.findById(id).populate("user").then((item: Item) => {
    console.log(item.user.name);
})

产生编译错误:

[ts] Property 'name' does not exist on type 'User | ObjectId'.
     Property 'name' does not exist on type 'ObjectId'.

问题

如何在 TypeScript 中拥有可以是两种类型之一的模型属性?

Question

How can I have a model property that can be either of two types in TypeScript?

推荐答案

你需要使用类型保护来缩小类型 Types.ObjectId |用户用户...

You need to use a type guard to narrow the type from Types.ObjectId | User to User...

如果你正在处理一个 User 类,你可以使用这个:

If you are dealing with a User class, you can use this:

if (item.user instanceof User) {
    console.log(item.user.name);
} else {
    // Otherwise, it is a Types.ObjectId
}

如果您有一个与 User 匹配的结构,但不是一个类的实例(例如,如果 User 是一个接口),您将需要一个自定义类型保护:

If you have a structure that matches a User, but not an instance of a class (for example if User is an interface), you'll need a custom type guard:

function isUser(obj: User | any) : obj is User {
    return (obj && obj.name && typeof obj.name === 'string');
}

可用于:

if (isUser(item.user)) {
    console.log(item.user.name);
} else {
    // Otherwise, it is a Types.ObjectId
}

如果您不想为此检查结构,您可以使用 歧视工会.

If you don't want to check structures for this purpose, you could use a discriminated union.

这篇关于TypeScript - 如何结合使用猫鼬填充定义模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆