Skip to content

TypeScript Type Incompatibility: Aggregate Builder unionWith cannot accept pipeline output #16033

@mustanggb

Description

@mustanggb

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

9.2.1

Node.js version

24.9.0

MongoDB server version

8.2.5

Typescript version (if applicable)

5.9.3

Description

There is a TypeScript type incompatibility in Mongoose's aggregate builder API. The .pipeline() method returns PipelineStage[] which includes all pipeline stages, but the .unionWith() method expects a more restrictive type that excludes certain stages like $merge.

This prevents using the aggregate builder's fluent API for $unionWith operations when trying to reuse pipeline outputs, forcing developers to fall back to array-based approaches.

Steps to Reproduce

  1. Create a simple aggregate pipeline using the builder
  2. Try to reuse that pipeline in .unionWith()
import mongoose, { Schema, Model } from 'mongoose';

// Simple Item schema
const itemSchema = new Schema({ text: String, published: Boolean });
const Item: Model<any> = mongoose.model('Item', itemSchema);

// Create base pipeline using aggregate builder
const basePipeline = Item.aggregate().match({ published: true });

// Try to reuse pipeline in unionWith - TypeScript error occurs here
const result = Item.aggregate()
  .match({ text: 'example' })
  .unionWith({
    coll: 'other_items',
    pipeline: basePipeline.pipeline() // ❌ TypeScript error
  });

TypeScript Error:

Type 'PipelineStage[]' is not assignable to type '(AddFields | Bucket | BucketAuto | ChangeStream | CollStats | Count | Densify | Facet | Fill | GeoNear | GraphLookup | Group | IndexStats | Limit | ListSearchIndexes | ListSessions | Lookup | Match | Merge | Out | PlanCacheStats | Project | Redact | ReplaceRoot | ReplaceWith | Sample | Search | SearchMeta | Set | Skip | Sort | SortByCount | Unset | Unwind | UnionWith)[]'.
  Type 'Merge' is not assignable to type 'AddFields | Bucket | BucketAuto | ...'

Expected Behavior

The code should compile successfully since baseAggregate.pipeline() returns valid pipeline stages that can be used in $unionWith. The aggregate builder's fluent API should allow reusing pipeline outputs in .unionWith() operations.

Additional Context

Root Cause: The issue is that PipelineStage[] includes Merge and other stages that are not allowed within $unionWith pipelines, but the aggregate builder's .pipeline() method returns the broader PipelineStage[] type.

Related Issues: Issue #11069 was fixed for array-based $unionWith usage (PR #11070), but this issue is specifically about the aggregate builder's fluent API compatibility.

Current State: There is currently no TypeScript-safe workaround. Even array-based approaches encounter similar typing issues with $unionWith pipeline definitions. Developers are forced to use type suppressions or assertions to work around these type incompatibilities.

Real-world Impact: In production applications using MongoDB's $unionWith to combine results from multiple collections, developers cannot use TypeScript safely without suppressing type errors. This defeats the purpose of TypeScript's type safety and creates potential runtime issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    new featureThis change adds new functionality, like a new method or classtypescriptTypes or Types-test related issue / Pull Request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions