最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using Mongoose and Typescript, what type should be used for a ref field of an interface? - Stack Overflow

programmeradmin0浏览0评论

I am using mongoose and Typescript, and I am wanting to know what type, or types, I should be using for a reference field, when creating an interface? Consider the following two related interfaces:

interface ICat {
  name: string,
  colour: string,
}

interface ICatDB extends ICat, Document {};

interface IMouse {
  name: string,
  colour: string,
  chasedBy: /* ... */
}

interface IMouseDB extends IMouse, Document {};

And the schemas and models that use them:

let cat = new Schema({
  name: String,
  colour: String,
});

mongoose.model<ICatDB>('Cat', cat);
let mouse = new Schema({
  name: String,
  colour: String,
  chasedBy: { type: Schema.Types.ObjectId, ref: 'Cat' }
});

mongoose.model<IMouseDB>('Mouse', mouse);

For the chasedBy field we need to consider that it can take values in three forms:

  • String or ObjectId, when passed to a create() method
  • ObjectId when returned from Mongoose
  • Instance of ICat when returned from Mongoose, using populate()

Is there a way that we can specify the types the interface can support, without having to resort to using any?

BTW we separated IMouse and IMouseDB, since Typescript wanted all the fields for Document filled out every time we created a new IMouse object, so this was a work around.

I am using mongoose and Typescript, and I am wanting to know what type, or types, I should be using for a reference field, when creating an interface? Consider the following two related interfaces:

interface ICat {
  name: string,
  colour: string,
}

interface ICatDB extends ICat, Document {};

interface IMouse {
  name: string,
  colour: string,
  chasedBy: /* ... */
}

interface IMouseDB extends IMouse, Document {};

And the schemas and models that use them:

let cat = new Schema({
  name: String,
  colour: String,
});

mongoose.model<ICatDB>('Cat', cat);
let mouse = new Schema({
  name: String,
  colour: String,
  chasedBy: { type: Schema.Types.ObjectId, ref: 'Cat' }
});

mongoose.model<IMouseDB>('Mouse', mouse);

For the chasedBy field we need to consider that it can take values in three forms:

  • String or ObjectId, when passed to a create() method
  • ObjectId when returned from Mongoose
  • Instance of ICat when returned from Mongoose, using populate()

Is there a way that we can specify the types the interface can support, without having to resort to using any?

BTW we separated IMouse and IMouseDB, since Typescript wanted all the fields for Document filled out every time we created a new IMouse object, so this was a work around.

Share Improve this question asked Mar 30, 2020 at 20:30 Andre MAndre M 7,5369 gold badges62 silver badges105 bronze badges 1
  • mongoose v7 improved the docs about TS types of populated documents. – Lin Du Commented May 25, 2023 at 9:15
Add a comment  | 

3 Answers 3

Reset to default 9

At least for version 5.x you could use this: https://mongoosejs.com/docs/5.x/docs/typescript/populate.html

import { PopulatedDoc } from 'mongoose';
import ICat from './ICat';

interface IMouse {
  name: string,
  colour: string,
  chasedBy: PopulatedDoc<ICat>
}

The docs in 6.x shows different approach:
https://mongoosejs.com/docs/typescript/populate.html
like this:

MouseModel.findOne({}).populate<{chasedBy: ICat}>('chasedBy');

Lacking any alternative answer, I went with:

import { ObjectID } from 'mongodb';
import ICat from './ICat';

interface IMouse {
  name: string,
  colour: string,
  chasedBy: string | ObjectID | ICat
}

This describes the type variants for the 'chasedBy' property. As to whether this is the recommended approach, I can't say.

Mongoose 6.x

Mongoose offers type declarations in mongoose.Types

interface Mouse { // important: don't use I in front of the name and don't extend Document
  chasedBy: mongoose.Types.ObjectId
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论