-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
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.19.1
Node.js version
20.x
MongoDB server version
5.x
Typescript version (if applicable)
5.9.3
Description
When defining a method on a Schema the this type of the function is automatically set to the hydrated document.
It makes sense (and the type definition also seems to have that intention) that this automatism only happens when the user does manually specify this.
It the case of base level documents, this can be worked around by introducing a static method that does the same thing. In the case of Subdocuments however, this is not possible, as the outer model migth not be known.
The relevant type definition at
Line 136 in dd39133
| type AddThisParameter<T, D> = { |
is
type ThisParameter<T, F> = T extends { (this: infer This): void } ? This : F;
type AddThisParameter<T, D> = {
[K in keyof T]: T[K] extends (...args: infer A) => infer R
? ThisParameter<T[K], unknown> extends unknown
? (this: D, ...args: A) => R
: T[K]
: T[K];
};Here the condition ThisParameter<T[K], unknown> extends unknown is always true as everything extends unknown.
This probably should be either
type ThisParameter<T, F> = T extends { (this: infer This): void } ? This : F;
type AddThisParameter<T, D> = {
[K in keyof T]: T[K] extends (...args: infer A) => infer R
? ThisParameter<T[K], never> extends never
? (this: D, ...args: A) => R
: T[K]
: T[K];
};or
type AddThisParameter<T, D> = {
[K in keyof T]: T[K] extends (this: infer This, ...args: infer A) => infer R
? (this: D, ...args: A) => R
: T[K];
};as everything extends unknown.
Steps to Reproduce
Consider
interface IUser {
name: string;
}
interface UserMethods {
printName(this: IUser): void;
}
const schema = new Schema<IUser, Model<IUser>, UserMethods>({ name: { type: String, required: true } });
schema.method('printName', function printName() {
console.log(this.name);
});
const User = model('user', schema);It this case I want to use printName on a lean document at some point like
let leanInst = await User.findOne({}).lean();
User.schema.methods.printName.apply(leanInst);This currently throws as the this type of printName is the hydrated user document.
Expected Behavior
The printName method to have the specified this type IUser, so that no TS error occurs.