Unable to use mongoose virtual with typescript

Viewed 627

I am trying to learn how to use virtuals with mongoose and typescript.

Say I have an interface for a user.

interface User {
    id: mongoose.ObjectId;
    name: string;
    likes: string;
}

Then I create a schema for mongoose.

// create the model
const user: mongoose.SchemaDefinition<User> = {
    name: { type: String },
    likes: { type: String },
};

// enable the use of virtuals
const options: mongoose.SchemaOptions = {
    toJSON: { getters: true, virtuals: true },
    toObject: { virtuals: true },
};

// create the scheme
const schema = new Schema(user, options);

Then I go to add a virtual and create my model.

// attach the virtual "bio" to return a string about the user
schema.virtual("bio").get(function (): string {
    return `Hi my name is ${this.name} and i like ${this.likes}`;
});

const model = mongoose.model("User", schema);

However, creating the virtual like above produces this error on this. See below picture.

enter image description here

So I thought that I could modify my virtual based on this post.

schema.virtual("bio").get(function (this: User): string {
    return `Hi my name is ${this.name} and i like ${this.likes}`;
});

const model = mongoose.model("User", schema);

However this does not work for me because my theory is that the following is set in my tsconfig "noUnusedLocals": true. I don't wan't to disable this because its a helpful linting rule. See below picture.

enter image description here

So my question is how can I create a mongoose virtual in typescript that does not throw an error like this, is there a simple example somewhere that I have missed while googling?

I guess one solution is to add // eslint-disable-next-line no-unused-vars to the line above to suppress the warning. However that does not explain why this is "unused". Even though it is.

I have even tried specifically using this by setting it to temporary variables (which get IntelliSense for the User interface, so its not like its ignoring the typing).

schema.virtual("bio").get(function (this: IUserModel): string {
    const name = this.name;
    const like = this.likes;
    return `Hi my name is ${name} and i like ${like}`;
});

Here's my full example as one copy-paste-friendly blob.

interface User {
    id: mongoose.ObjectId;
    name: string;
    likes: string;
}

const user: mongoose.SchemaDefinition<User> = {
    name: { type: String },
    likes: { type: String },
};

const options: mongoose.SchemaOptions = {
    toJSON: { getters: true, virtuals: true },
    toObject: { virtuals: true },
};

const schema = new Schema(user, options);

// this is defined but never used :(
schema.virtual("bio").get(function (this: User): string {
    return `Hi my name is ${this.name} and i like ${this.likes}`;
});

const model = mongoose.model("User", schema);

export default model;
1 Answers

You need to set these properties if you're working on typescript

user.set("toObject", { virtuals: true });
user.set("toJSON", { virtuals: true });
Related