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

Incorrect inferred return type for distinct() on array fields #14026

Closed
2 tasks done
richardsimko opened this issue Nov 1, 2023 · 13 comments · Fixed by #14047
Closed
2 tasks done

Incorrect inferred return type for distinct() on array fields #14026

richardsimko opened this issue Nov 1, 2023 · 13 comments · Fixed by #14047
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@richardsimko
Copy link

richardsimko commented Nov 1, 2023

Prerequisites

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

Mongoose version

8.0.0

Node.js version

20.0.0

MongoDB server version

6.0

Typescript version (if applicable)

latest

Description

The inferred return type for distinct() queries with an array fields is incorrect. It's inferred to be string[][] for a string[] field when in fact it should be string[]

Steps to Reproduce

interface Foo {
  bar: string[];
}

const FooModel = model<Foo>('Foo', new Schema<Foo>({ bar: [String] }));

await FooModel.create({ bar: ['a', 'b'] })

const distinctBar = await FooModel.distinct('bar');
console.log(distinctBar); // [ 'a', 'b' ]

distinctBar is actually a string[] but the inferred return type is string[][].

Expected Behavior

Inferred return type does not add Array to a type which is already an Array

@vkarpov15 vkarpov15 added this to the 8.0.1 milestone Nov 1, 2023
@vkarpov15 vkarpov15 added the typescript Types or Types-test related issue / Pull Request label Nov 1, 2023
@donoftime2018
Copy link

donoftime2018 commented Nov 2, 2023

distinct is actually returning an array of String arrays. bar is a String[] and distinct selects all unique String arrays within an array. So since distinct is returning an array of String arrays with one item it'll look something like this:

[
bar: []
]

@richardsimko
Copy link
Author

@donoftime2018 No, distinct() returns an array of strings when run on a field with string[] type. See the Mongo docs. I've confirmed this is the case for mongoose as well.

Here's an amended example:

interface Foo {
  bar: string[];
}

const FooModel = model<Foo>('Foo', new Schema<Foo>({ bar: [String] }));

await FooModel.create({ bar: ['a', 'b'] })

const distinctBar = await FooModel.distinct('bar');
console.log(distinctBar); // [ 'a', 'b' ]

I've edited the description as well to explain this

@donoftime2018
Copy link

donoftime2018 commented Nov 2, 2023

Try adding more documents to the collection so you can see what I am talking about or updating your version of mongoose

@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Nov 2, 2023
@IslandRhythms
Copy link
Collaborator

IslandRhythms commented Nov 2, 2023

Upon further testing comes back as string[][]

import * as mongoose from 'mongoose';

interface Foo {
  bar: string[];
}

const FooModel = mongoose.model<Foo>('Foo', new mongoose.Schema<Foo>({ bar: [String] }));

async function run() {
  await mongoose.connect('mongodb://localhost:27017');
  await mongoose.connection.dropDatabase();
  await FooModel.create({ bar: ['a', 'b'] })
  await FooModel.create({ bar: ['c','d']});
  await FooModel.create({ bar: ['e','f']})

  const distinctBar = await FooModel.distinct('bar');
  console.log(distinctBar); // [ 'a', 'b', 'c', 'd', 'e', 'f' ]
}

run();

@donoftime2018
Copy link

Shall I report this as a bug?

@richardsimko
Copy link
Author

@donoftime2018 That does sound like a separate bug, yes. I couldn't find anything in neither the mongo nor mongoose docs pointing to the behavior you mentioned being correct. As @IslandRhythms mentioned the type is string[][] even when the returned value is string[] (Thanks for confirming :) )

@donoftime2018
Copy link

Np

@IslandRhythms
Copy link
Collaborator

@donoftime2018 please open a new issue and follow the template if you have a bug to report.

@donoftime2018
Copy link

How?

@IslandRhythms
Copy link
Collaborator

IslandRhythms commented Nov 3, 2023

From this page on the top right next to this issue title you should see a new issue button.

@donoftime2018
Copy link

I wanna take a go and fix this issue via code so what should I do?

@donoftime2018
Copy link

donoftime2018 commented Nov 4, 2023

type_issue(2)

import * as mongoose from 'mongoose';
import { type } from 'os';

interface Foo {
bar: String;
bar_num: Number;
}

const FooModel = mongoose.model('Foo', new mongoose.Schema({ bar: [String], bar_num: [Number] }));

async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
await FooModel.create({ bar: ['a', 'b'], bar_num: [0, 2]})
await FooModel.create({ bar: ['c','d'], bar_num: [1, 2] });
await FooModel.create({ bar: ['e','f'], bar_num: [5]})

const distinctBar = await FooModel.distinct('bar');
const distinctBars = await FooModel.distinct('bar_num');
console.log(distinctBar); // [ 'a', 'b', 'c', 'd', 'e', 'f' ]
console.log(distinctBars); // [0, 1, 2 5]
//distinctBar is String[] and distinctBars is Number[]
}

run();

The inferred types are String[] and Number[] after removing the array brackets from interface Foo

vkarpov15 added a commit that referenced this issue Nov 6, 2023
types(model+query): unpack arrays in distinct return type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants