Skip to content

Conversation

vkarpov15
Copy link
Collaborator

Fix #10894. There's still work to do on this PR (TypeScript types, options testing, thinking about how to handle getters/setters on unions) but I wanted to get this out there for review.

Summary

type: 'Union' means a given path can be one of multiple types.

For example, in the following schema, purchased can be either a Boolean or a Date.

const schema = new Schema({
  purchased: {
    type: 'Union',
    of: [Boolean, Date]
  }
});

Order matters in of: Mongoose will loop through the Of schema types and take the first one that casts successfully, unless one of the schema types returns the original value, in which case Mongoose just takes the original value.

For example, in the above case, purchased: 1 would get converted to a boolean (true) because Mongoose can cast 1 -> true. But purchased: 2 would get converted to a Date, because 2 is not a value Mongoose can cast to a Boolean by default.

Examples

Copilot

This comment was marked as outdated.

Copy link
Collaborator

@hasezoey hasezoey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, though lint would need to be fixed and as Copilot already pointed out, the documentation for of still refers to maps.

@hasezoey hasezoey added the new feature This change adds new functionality, like a new method or class label Aug 11, 2025
@vkarpov15 vkarpov15 requested a review from Copilot August 20, 2025 17:05
@vkarpov15 vkarpov15 changed the base branch from master to 8.18 August 20, 2025 17:05
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces support for union types in Mongoose schemas, allowing a schema path to be one of multiple types. It implements a new Union schema type with casting logic that tries each type in order and uses the first successful cast.

  • Adds a new Union schema type that accepts an array of possible types in an of property
  • Implements casting logic that preserves original values when possible and falls back to first successful cast
  • Updates error messages to include string length information for better debugging

Reviewed Changes

Copilot reviewed 7 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
lib/schema/union.js Implements the core Union schema type with casting and setter logic
lib/schema/index.js Exports the new Union schema type
lib/schema.js Updates schema interpretation to handle Union types
lib/options/schemaUnionOptions.js Defines options class for Union schema type
lib/schemaType.js Adds string length information to validation error context
lib/error/messages.js Updates error messages to include string length
test/schema.union.test.js Comprehensive test suite for Union functionality
test/types/schema.test.ts TypeScript type tests for Union schema inference

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@vkarpov15 vkarpov15 merged commit 8f80bc7 into 8.18 Aug 21, 2025
74 of 75 checks passed
@@ -188,7 +188,7 @@ declare module 'mongoose' {
_id?: boolean;

/** If set, specifies the type of this map's values. Mongoose will cast this map's values to the given type. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should likely mention that the property is also valid for Union now.

@hasezoey hasezoey deleted the vkarpov15/gh-10894 branch August 23, 2025 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature This change adds new functionality, like a new method or class
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Union schema types: paths that can be one of multiple types
2 participants