Skip to content

TypeScript: Regression in allowing Virtuals with Setters in Document creation/initialization after upgrading to v9 #16012

@nikzanda

Description

@nikzanda

Prerequisites

  • I have written a descriptive issue title

Mongoose version

9.1.6

Node.js version

24.11.0

MongoDB version

6.0.2

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

No response

Issue

After upgrading from Mongoose 8 to Mongoose 9, I've encountered a strict typing issue when initializing documents that contain subdocuments with virtual setters.

In Mongoose 8, it was possible to pass a value to a virtual field (which has a setter) during document creation. In Mongoose 9, the TypeScript compiler throws an error, forcing the use of the raw database paths instead of the virtual path.

Schema setup

I have a decimalSchema used as a subdocument. It stores a number as base and exponent but exposes a value virtual for ease of use:

import {
  HydratedSingleSubdocument,
  Model,
  Schema,
  SchemaOptions,
  SchemaTypes,
} from 'mongoose';

export interface IDecimal {
  base: number;
  exponent: number;
}

export interface IDecimalVirtuals {
  value: number;
}

export type DecimalInstance = HydratedSingleSubdocument<IDecimal, IDecimalVirtuals>;

type DecimalModelType = Model<IDecimal, {}, {}, IDecimalVirtuals, DecimalInstance>;

type DecimalSchemaOptions = SchemaOptions<
  IDecimal,
  {},
  {},
  {},
  IDecimalVirtuals,
  DecimalInstance,
  DecimalModelType
>;

const options: DecimalSchemaOptions = {
  _id: false,
  toJSON: { virtuals: true },
  toObject: { virtuals: true },
};

const decimalSchema = new Schema<
  IDecimal,
  DecimalModelType,
  {},
  {},
  IDecimalVirtuals,
  {},
  DecimalSchemaOptions,
  IDecimal,
  DecimalInstance
>({
  base: {
    type: SchemaTypes.Number,
    required: true,
  },
  exponent: {
    type: SchemaTypes.Number,
    required: true,
  },
}, options);

decimalSchema.virtual('value')
  .get((_value, _virtual, doc) => fromDecimal(doc)) // returns number
  .set((value: number, _virtual, doc) => doc.set(toDecimal(value))); // converts number to IDecimal

export default decimalSchema;

The issue

When I try to create a parent document containing this subdocument:

// Parent Schema usage
const parentSchema = new Schema({
  quantity: decimalSchema
});

// Mongoose 8: Worked fine
// Mongoose 9: Type Error
const doc = new ParentModel({
  quantity: { value: 10 } 
});

I would like to know if there is a recommended way in Mongoose 9 to allow virtuals with setters to be accepted as valid input types during document initialization/creation, or if this is a regression in the new type inference engine.

Ideally, the inferred type for the document constructor should include keys from IDecimalVirtuals if they have a setter defined, or allow us to merge virtuals into the "Input" type of the schema more easily.

Metadata

Metadata

Assignees

No one assigned

    Labels

    helpThis issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessaryhelp wantedtypescriptTypes or Types-test related issue / Pull Request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions