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

FilterQuery Typing fails for generic type #14459

Closed
2 tasks done
david-loe opened this issue Mar 22, 2024 · 5 comments
Closed
2 tasks done

FilterQuery Typing fails for generic type #14459

david-loe opened this issue Mar 22, 2024 · 5 comments
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@david-loe
Copy link

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.2.3

Node.js version

20

MongoDB server version

7.0.6

Typescript version (if applicable)

5.4.3

Description

Repro Script throws

No overload matches this call.
  Overload 1 of 5, '(filter: FilterQuery<ModelType>, projection?: ProjectionType<ModelType> | null | undefined, options?: QueryOptions<ModelType> | null | undefined): Query<...>', gave the following error.
    Argument of type '{ _id: string | Types.ObjectId; }' is not assignable to parameter of type 'FilterQuery<ModelType>'.
      Type '{ _id: string | Types.ObjectId; }' is not assignable to type '{ [P in keyof ModelType]?: Condition<ModelType[P]> | undefined; }'.
  Overload 2 of 5, '(filter: FilterQuery<ModelType>, projection?: ProjectionType<ModelType> | null | undefined): Query<IfAny<ModelType, any, Document<...> & Require_id<...>>[], IfAny<...>, {}, ModelType, "find">', gave the following error.
    Argument of type '{ _id: string | Types.ObjectId; }' is not assignable to parameter of type 'FilterQuery<ModelType>'.
      Type '{ _id: string | Types.ObjectId; }' is not assignable to type '{ [P in keyof ModelType]?: Condition<ModelType[P]> | undefined; }'.
  Overload 3 of 5, '(filter: FilterQuery<ModelType>): Query<IfAny<ModelType, any, Document<unknown, {}, ModelType> & Require_id<ModelType>>[], IfAny<...>, {}, ModelType, "find">', gave the following error.
    Argument of type '{ _id: string | Types.ObjectId; }' is not assignable to parameter of type 'FilterQuery<ModelType>'.
      Type '{ _id: string | Types.ObjectId; }' is not assignable to type '{ [P in keyof ModelType]?: Condition<ModelType[P]> | undefined; }'.ts(2769)

Steps to Reproduce

import { Model, Types } from "mongoose";

function findById<ModelType extends {_id: Types.ObjectId | string}>(model: Model<ModelType>, _id: Types.ObjectId | string){
    return model.find({_id: _id})
}

Expected Behavior

No Error

@IslandRhythms IslandRhythms added the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label Mar 22, 2024
@david-loe
Copy link
Author

Error comes from v8.2.3.
v8.2.2 doesn't had this issue.

@david-loe
Copy link
Author

related to #14462

@vkarpov15 vkarpov15 added typescript Types or Types-test related issue / Pull Request and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Mar 29, 2024
@vkarpov15 vkarpov15 added this to the 8.2.5 milestone Mar 29, 2024
@vkarpov15
Copy link
Collaborator

Looks like OP's script fails to compile with TypeScript 5.4.3:

$ ./node_modules/.bin/tsc --strict gh-14459.ts 
gh-14459.ts:4:23 - error TS2769: No overload matches this call.
  Overload 1 of 5, '(filter: FilterQuery<ModelType>, projection?: ProjectionType<ModelType> | null | undefined, options?: QueryOptions<ModelType> | null | undefined): Query<...>', gave the following error.
    Argument of type '{ _id: string | Types.ObjectId; }' is not assignable to parameter of type 'FilterQuery<ModelType>'.

I think this is just a limitation of TypeScript, because { _id: never } does satisfy extends {_id: Types.ObjectId | string}. For example, the following doesn't cause any errors with using { _id: never }:

import { Model, Types, model, Schema } from "mongoose";

function findById<ModelType extends {_id: Types.ObjectId | string}>(model: Model<ModelType>, _id: Types.ObjectId | string){
    return model.find({_id: _id})
}

type ModelType = { _id: never };
const TestModel = model<ModelType>('test', new Schema());

findById<ModelType>(TestModel, 'foo');

We will take a quick look to see if there's some way we can work around this weird never case

wdhdev added a commit to wdhdev/reminders that referenced this issue Apr 2, 2024
@vkarpov15
Copy link
Collaborator

I took a look but there's nothing we can do other than 1) make FilterQuery<T> = any, or 2) require as FilterQuery in OP's case as follows:

import { Model, Types, model, Schema, FilterQuery } from "mongoose";

function findById<ModelType extends {_id: Types.ObjectId | string}>(model: Model<ModelType>, _id: Types.ObjectId | string){
    return model.find({_id: _id} as FilterQuery<ModelType>);
}

This is suboptimal, but unfortunately a limitation of TypeScript. From this SO answer: "Never assign a concrete type to a generic type parameter, consider it as read-only!". That includes calling a function with arguments that rely on the generic type parameter.

Even if we make FilterQuery<T> = T, we get the following error '{ _id: string | Types.ObjectId; }' is assignable to the constraint of type 'ModelType', but 'ModelType' could be instantiated with a different subtype of constraint '{ _id: string | ObjectId; }'

Given that { _id: never } extends {_id: Types.ObjectId | string}, the TypeScript limitation makes sense, just quirky language design.

@vkarpov15 vkarpov15 removed this from the 8.3.1 milestone Apr 5, 2024
@vkarpov15 vkarpov15 added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Apr 5, 2024
@vkarpov15 vkarpov15 reopened this Apr 8, 2024
@vkarpov15 vkarpov15 added this to the 8.3.1 milestone Apr 8, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.3.1, 8.3.2 Apr 8, 2024
@vkarpov15
Copy link
Collaborator

Fixed by #14510

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants