-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Breaking TypeScript Change in find from v8.5.5 to v8.6.0 #14863
Comments
For example: |
@isnifer We fixed $expr with #14845, will ship that release shortly. @Towerss in this case, what do you think about just using a type assertion? const defaults = await model
.find({
createdForType: 'system', // This field is not defined in ExampleSchema
isActive: true,
isCustom: false,
} as RootFilterQuery<T>)
.lean()
.exec(); That seems to compile, and #14764 can be very useful for catching issues like #14862, so I think retaining #14764 may have some merit. Another option would be to add some type restrictions on // Define a simple schema with a limited number of fields
interface ExampleDoc extends Document {
createdForType: string;
isActive: boolean;
isCustom: boolean;
}
const ExampleSchema = new Schema<ExampleDoc>({
isActive: Boolean,
isCustom: Boolean
});
const ExampleModel: Model<ExampleDoc> = mongoose.model<ExampleDoc>('Example', ExampleSchema);
async function initializeRelatedParametersHelper<T extends ExampleDoc>(
model: Model<T>,
createdForId: Types.ObjectId,
createdForType: string,
trainingZoneId: Types.ObjectId
): Promise<void> { What do you think of these alternatives? |
Thanks for the suggestions. I understand that the stricter type definitions help with type safety and catching errors early. However, I still see this as a breaking change because it requires developers to update existing code that was previously valid, leading to TypeScript errors and CI/CD pipeline failures until the code is modified. This fits the definition of a breaking change as it breaks backward compatibility. To adapt to the new types, I had to dynamically check for schema fields and build the filter object accordingly:
While this works, it adds complexity compared to the previous approach. Regarding the suggestion to use a type assertion like:
This approach is a quick fix but bypasses type safety, which could lead to potential bugs if the fields don’t exist in some schemas. It also reduces the benefits of stricter typing. If you are not careful, using type assertions can introduce bugs. For example, if createdForType truly does not exist in some schemas, the query could fail at runtime or return unexpected results. Also, future developers may not understand why a type assertion was used and could introduce changes that break assumptions, leading to hidden bugs. I think a more gradual change—such as temporarily allowing both RootFilterQuery and FilterQuery with a deprecation notice—could have made the transition smoother for developers while still moving towards improved type safety in version 9.x Thanks for considering this feedback. |
I'm a bit surprised of having my pipeline breaking this morning. I feel like it is Breaking Change too. |
Related issue |
The To be specific: the tests for |
Would also like to see this reverted |
Prerequisites
Mongoose version
8.6.0
Node.js version
20.15.1
MongoDB server version
7
Typescript version (if applicable)
5.5.4
Description
Hi Mongoose team,
Mongoose version 8.6.0 introduced a breaking change in the type definitions for the find method. The filter parameter type was changed from FilterQuery to RootFilterQuery, which no longer allows fields or operators that are not explicitly defined in the schema.
This change significantly affects the use of generic utility functions in TypeScript. For example, functions designed to operate across multiple Mongoose models with different schemas (using a generic Model) now fail to compile when using dynamically added fields or common filters that are not explicitly declared in every schema.
Previously, the more permissive FilterQuery allowed such flexibility, enabling code reuse and reducing code duplication across models. The stricter typing of RootFilterQuery now forces developers to either:
Refrain from using dynamic fields or filters that are not explicitly defined in the schema.
Resort to less type-safe workarounds, such as using type assertions or @ts-ignore, to bypass TypeScript errors.
Steps to Reproduce
Expected Behavior
TypeScript should compile without errors, allowing the flexibility to use generic utility functions across different models with dynamic fields or query parameters not strictly defined in the schema.
The text was updated successfully, but these errors were encountered: