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

lean() conflicts with Map type returned by InferSchemaType #13010

Closed
2 tasks done
Jokero opened this issue Feb 8, 2023 · 2 comments
Closed
2 tasks done

lean() conflicts with Map type returned by InferSchemaType #13010

Jokero opened this issue Feb 8, 2023 · 2 comments
Labels
enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@Jokero
Copy link
Contributor

Jokero commented Feb 8, 2023

Prerequisites

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

Issue

InferSchemaType returns Map type for a field of type Map, which is perfectly fine for full queries like Model.findOne(), but does not work for lean queries Model.findOne().lean():

import mongoose, { InferSchemaType, model, Schema } from 'mongoose';

const schema = new Schema({
    name: { required: true, type: Map, of: String },
});

// infers { name: Map<string, string> }
export type CountryRaw = InferSchemaType<typeof schema>;

export const CountryModel = model('Country', schema);

(async () => {
    await mongoose.connect('mongodb://localhost/test');

    await CountryModel.create({
        name: {
            en: 'Croatia',
            ru: 'Хорватия',
        },
    });

    const country: CountryRaw | null = await CountryModel.findOne().lean().exec();
    if (country) {
        // produces "TypeError: country.name.get is not a function",
        // because country.name is a plain object, not a Map
        console.log('country name', country.name.get('en'));
    }
})();

Possible solution or quick fix is to allow to pass some flag to lean() function that will tell to convert plain object to a Map object:

// country.name will be a Map
const country: CountryRaw | null = await CountryModel.findOne().lean({ convertToMap: true }).exec();

Or maybe even better to use a special plugin for it.

@IslandRhythms IslandRhythms added the typescript Types or Types-test related issue / Pull Request label Feb 8, 2023
@vkarpov15 vkarpov15 added this to the TypeScript backlog milestone Feb 12, 2023
@Jokero
Copy link
Contributor Author

Jokero commented Feb 26, 2023

@vkarpov15 This problem is actually present in plain JS as well, because Map type will have different value in case of lean and hydrated queries. Just wanted to clarify

@vkarpov15
Copy link
Collaborator

@Jokero that's unfortunately expected behavior. Lean means you get back the raw document as it is stored in MongoDB. And MongoDB doesn't have a map type, just objects. We'll have to figure out a workaround for this, but I think the lean({ inflateMaps: true }) option is a good workaround.

@vkarpov15 vkarpov15 modified the milestones: TypeScript backlog, 7.1.0 Feb 27, 2023
@vkarpov15 vkarpov15 added the enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature label Feb 27, 2023
vkarpov15 added a commit that referenced this issue Apr 25, 2023
types(query): make `lean()` flatten out inferred maps into Record<string, V>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants