Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.94k stars 3.84k forks source link

Issue with InferRawDocType, not resulting in simple js array, but instead as DocumentArray #14954

Open sasp1 opened 2 weeks ago

sasp1 commented 2 weeks ago

Prerequisites

Mongoose version

8.7.1

Node.js version

16.x

MongoDB server version

8.0.0

Typescript version (if applicable)

5.2.2

Description

Hello. I am trying to migrate from mongoose 7.x to 8.7.1 and I am running into some issues with using the new InferRawDocType. Specifically, I get an error when type inferring from objects with "double-nested" schemas, meaning schemas that are nested twice (see example below). The relatively simple example below illustrates how InferRawDocType doesn't work properly and doesn't translate the definitions to simple js arrays or POJOs. But when I omit the "double-nested" type and recreate it, it works fine (see Squad1 type).

Mongo docs state that using InferRawDocType should result in raw document type like doc.toObject(). (see docs here), but this doesn't happen as the example illustrates

We also tried sticking with what we had before with InferSchemaType but it gives similar Typescript errors with object not containing DocumentArray props.

This is a huge pain for us as we want to update to new MongoDB 8.0 and mongoose 8.x, but are stuck with typescript errors when migrating.


import { InferRawDocType, Schema } from "mongoose";

const roleDef = {
  name: { type: String, required: true },
};

const tacticDef = {
  roles: [new Schema(roleDef)],
};

type Tactic = InferRawDocType<typeof tacticDef>;

const tacticSchema = new Schema(tacticDef);

const squad = {
  tactic: {
    type: tacticSchema,
  },
};

type Squad1 = Omit<InferRawDocType<typeof squad>, "tactic"> & {
  tactic: Tactic;
};

type Squad2 = InferRawDocType<typeof squad>;

// This code does not give any Typescript errors
const squad1: Squad1 = {
  tactic: {
    roles: [{ name: "name"}],
  },
};

// Code below gives typescript error, saying that roles need to have properties of document array
const squad2: Squad2 = {
  tactic: {
    roles: [{ name: "name" }],
  },
};

Thanks

Steps to Reproduce

Copy and paste the code from the description into any project with Typescript and mongoose 8.7.1 and you should see typescript error on squad2, which shouldn't happen.

Expected Behavior

Using InferRawDocType, this type should be POJOs or simple js arrays. Not DocumentArray, where props like $isSingleNested, $parent etc. is needed

vkarpov15 commented 2 weeks ago

This issue is unfortunately fairly tricky to fix, we have a rough pass as a fix in #14962 but you should use your workaround for now. I'm sorry for the trouble.