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

Viewed 2928

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.

3 Answers

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
}
Related