question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

TS Error specifically with `lean` result

See original GitHub issue

Prerequisites

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

Mongoose version

6.3.5

Node.js version

18.2.0

MongoDB server version

4.5.0

Description

Firstly, Thanks for the amount of effort you put into this package.

The way the new lean type is computed is very frustrating to use. With the object keys it omits from the type and repeated computed names, it makes it hard to understand what the actual result type will be by just hovering over the variable.

I upgraded from v6.3.1 to v6.3.5 and the changes broke the lean result type in my application. The ObjectId type I use is defined with the one in bson as well.

import { ObjectId } from "bson";
import { Schema } from "mongoose";

type ObjectId = ObjectId & Schema.Types.ObjectId;

I do it this way to take advantage of the bson type definition for an ObjectId. Like with the .equals method to test the equality of an ObjectIdLike variable with the ObjectId. TS reported the property doesn’t exist in the lean return type, but I tested and it did.

I edited the definition of your types for the LeanResult to something more straightforward, the error was resolved and it was easier to glance at the type when I hovered over the variable.

// https://github.com/Automattic/mongoose/blob/9875dbf53be7b1a4652ab3ac57db2a881999889a/types/index.d.ts#L529
export type LeanDocument<T> = {
  [K in keyof Omit<T, Exclude<keyof Document, '_id' | 'id' | '__v'> | '$isSingleNested'>]: T[K] extends never[] ? never[] : T[K] extends Document[] ? Array<LeanDocument<T[K][number]>> : T[K] extends unknown[] ? T[K][number] extends Document ? Array<LeanDocument<T[K][number]>> : T[K] : T[K] extends Document ? LeanDocument<T[K]> : T[K];
};
// https://github.com/Automattic/mongoose/blob/9875dbf53be7b1a4652ab3ac57db2a881999889a/types/query.d.ts#L422
lean<LeanResultType = ResultType extends unknown[] ?  Array<LeanDocument<Require_id<RawDocType>>> : LeanDocument<Require_id<RawDocType>> | null>(val?: boolean | any): QueryWithHelpers<LeanResultType, DocType, THelpers, RawDocType>;

I’ve tested it with your tests defined in https://github.com/Automattic/mongoose/blob/9875dbf53be7b1a4652ab3ac57db2a881999889a/test/types/lean.test.ts and it works as well.

This is what it looks like with the current LeanDocument definition

Screenshot 2022-06-06 at 13 36 04

Notice the 52+ properties omitted from the result


Also, In the definition for the Require_id

https://github.com/Automattic/mongoose/blob/9875dbf53be7b1a4652ab3ac57db2a881999889a/types/index.d.ts#L94

After checking if it extends a _id, doing this (T & { _id: T['_id'] }) again rather than just using the T type since it already has the _id property only causes it to look more unorganised in the hover tooltip.

Using (T & { _id: T['_id'] })

Screenshot 2022-06-06 at 13 17 11

Using T

Screenshot 2022-06-06 at 13 18 57

Please let me know what you think about this.

If there is something you’ll like to change or a reason why you wouldn’t want this change.

Otherwise, if it’s fine and you have no other worries about the changes, I can open a PR for it. Thanks

Steps to Reproduce

  1. Make an ObjectId type with bson’s definition and mongoose’s definition
  2. Define a Schema using the ObjectId above as its _id type
  3. Query that Model and lean the result.
  4. Attempt to use the .equals method with a string or another variable.
import { ObjectId } from "bson";
import { Schema } from "mongoose";

type Book = {
  _id: ObjectId & Schema.Types.ObjectId;
  title: string;
}

const BookSchema = new Schema<Book>({ title: { type: String } });
const BookModel = model("book", BookSchema);

async function run() {
  const { _id } = await BookModel.create({
    title: "Book Title 👍"
  });
  const res = await BookModel.findOne({}).lean();
  res?._id.equals(_id) // TS Error
}

run();

Expected Behavior

Not to have the Typescript error.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
vkarpov15commented, Jul 1, 2022

I thought about it, but & { _id: T['_id'] } is actually important because that makes _id required in the output. Some devs may make _id optional in their document definition, although we don’t recommend that.

0reactions
iammolacommented, Jun 19, 2022

@vkarpov15

After I reposted the script, I tried the Types.ObjectId definition and it was exactly what I was trying to get from extending with bson’s definitions. I don’t know how I forgot to comment on it, so I’m sorry for that.

With that said, I’ll appreciate if you still consider improving the visibility of the lean type when the variable is hovered over. It’s not as important, but personally it’s something that I feel will be massively appreciated.

Thanks again for your work on the package.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A functional (programming) approach to error handling in ...
It is saying errors are a possible outcome explicitly by making the error one of the possible returned values. It can even have...
Read more >
TypeScript Express tutorial #3. Error handling and validating ...
Express Error handling middleware. First, let's create a class that we are going to use to throw errors. src/exceptions/HttpException.ts ...
Read more >
node.js - Using `lean` on mongoose queries that return arrays ...
The problem is when I try to use it with a query that returns multiple results: let somethings:Something[]; SomethingDocument.find({color:'blue'}) ...
Read more >
The Lean Reference Manual
outcome of a #print or #check command. The keystrokes C-c C-n toggle Lean-Next-Error mode, in which ... For more information on a specific...
Read more >
true-myth/true-myth - handling in TypeScript. - GitHub
A library for safe, idiomatic null and error handling in TypeScript, with Maybe and Result types, supporting both a functional style and a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found