Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findOneAndReplace should not require functions to exist on the replacement document #10714

Closed
lantw44 opened this issue Sep 13, 2021 · 1 comment
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@lantw44
Copy link
Contributor

lantw44 commented Sep 13, 2021

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Model.findOneAndReplace requires functions to exist on the replacement document. This is basically the same as #10144 except for the method name.

index.ts:33:60 - error TS2345: Argument of type '{ someProp: string; }' is not assignable to parameter of type '_AllowStringsForIds<LeanDocument<DocumentType<User, BeAnObject>>>'.
  Property 'someFunction' is missing in type '{ someProp: string; }' but required in type '_AllowStringsForIds<LeanDocument<DocumentType<User, BeAnObject>>>'.

33   await UserModel.findOneAndReplace({ someProp: "hello" }, { someProp: "hi" });
                                                              ~~~~~~~~~~~~~~~~~~

  index.ts:18:3
    18   someFunction(): string;
         ~~~~~~~~~~~~~~~~~~~~~~~
    'someFunction' is declared here.


Found 1 error.

If the current behavior is a bug, please provide the steps to reproduce.
Copy the example from #10144 and add await UserModel.findOneAndReplace({ someProp: "hello" }, { someProp: "hi" }); after the UserModel.insertMany call.

package.json

{
  "name": "test",
  "version": "1.0.0",
  "license": "ISC",
  "dependencies": {
    "mongoose": "^5.13.9"
  },
  "devDependencies": {
    "@types/node": "^14.17.15",
    "typescript": "^4.4.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "strict": true,
    "esModuleInterop": true
  }
}

index.ts

import mongoose from 'mongoose';

class User {
  public someProp!: string;
}

type DocumentType<T, QueryHelpers = BeAnObject> = (T extends { _id: unknown; }
  ? mongoose.Document<T["_id"], QueryHelpers> & T
  : mongoose.Document<any, QueryHelpers> & T) &
  IObjectWithSomeFunction;

type ModelType<T, QueryHelpers = BeAnObject> = mongoose.Model<DocumentType<T, QueryHelpers>, QueryHelpers>;
type ReturnModelType<U extends AnyParamConstructor<any>, QueryHelpers = BeAnObject> = ModelType<InstanceType<U>, QueryHelpers> & U;

type AnyParamConstructor<T> = new (...args: any) => T;
type BeAnObject = Record<string, any>;
interface IObjectWithSomeFunction {
  someFunction(): string;
}

const UserSchema = new mongoose.Schema({ someProp: String, someOtherProp: [String] });
const UserModel: ReturnModelType<typeof User> = mongoose.model<DocumentType<User>, ReturnModelType<typeof User>>("User", UserSchema);

(async () => {
  await mongoose.connect('mongodb://localhost:27017/test', {
    useNewUrlParser: true,
    useFindAndModify: false,
    useCreateIndex: true,
    useUnifiedTopology: true,
  });

  await UserModel.insertMany([{ someProp: "hello" }]);
  await UserModel.findOneAndReplace({ someProp: "hello" }, { someProp: "hi" });

  await mongoose.disconnect();
})();

What is the expected behavior?
It should not require functions to exist on the replacement document.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Node.js 14.17.0
Mongoose 5.13.9
MongoDB 5.0.2

@IslandRhythms IslandRhythms added the typescript Types or Types-test related issue / Pull Request label Sep 13, 2021
@IslandRhythms
Copy link
Collaborator

// NodeJS: 14.16.1
import * as mongoose from "mongoose"; // mongoose@5.12.4

class User {
  public someProp!: string;
}

// Note: "ModelType" and "ReturnModelType" are seperated, because they are used in different stages & with different cases in mind
type DocumentType<T, QueryHelpers = BeAnObject> = (T extends { _id: unknown; }
  ? mongoose.Document<T["_id"], QueryHelpers> & T
  : mongoose.Document<any, QueryHelpers> & T) &
  IObjectWithSomeFunction; // this is here, because all models / documents made with this have this at runtime

type ModelType<T, QueryHelpers = BeAnObject> = mongoose.Model<DocumentType<T, QueryHelpers>, QueryHelpers>;
// the "& U" is to add all "statics" (like static functions) onto the model type
type ReturnModelType<U extends AnyParamConstructor<any>, QueryHelpers = BeAnObject> = ModelType<InstanceType<U>, QueryHelpers> & U;

type AnyParamConstructor<T> = new (...args: any) => T;
type BeAnObject = Record<string, any>;
interface IObjectWithSomeFunction {
  someFunction(): string;
}

const UserSchema = new mongoose.Schema({ someProp: String, someOtherProp: [String] });
const UserModel: ReturnModelType<typeof User> = mongoose.model<DocumentType<User>, ReturnModelType<typeof User>>("User", UserSchema);

(async () => {
  await mongoose.connect(`mongodb://localhost:27017/`);

  // the following code line is what errors
  await UserModel.insertMany([{ someProp: "hello" }]);
  await UserModel.findOneAndReplace({someProp: 'hello'}, {someProp: 'hi'});

  await mongoose.disconnect();
})();

@vkarpov15 vkarpov15 added this to the 6.0.10 milestone Sep 15, 2021
@vkarpov15 vkarpov15 modified the milestones: 6.0.10, 5.13.10 Oct 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants