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

"this" context has "any" type in Schema methods option #14027

Closed
2 tasks done
ruxxzebre opened this issue Nov 1, 2023 · 4 comments
Closed
2 tasks done

"this" context has "any" type in Schema methods option #14027

ruxxzebre opened this issue Nov 1, 2023 · 4 comments
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@ruxxzebre
Copy link
Contributor

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 (same case as 7.2.2)

Node.js version

20.5.0 (same case as 18.0.0)

MongoDB server version

7.0

Typescript version (if applicable)

5.2.2 (recently updated, same case with 4.8.4)

Description

As stated here, issue with this context was fixed, if we declare methods like this:

schema.method("fullName", function fullName() {
    return this.firstName + " " + this.lastName;
});

But, if we're trying to specify methods in schema's method option AND provide IUserMethods into a Schema generic, this becomes any once again.

new Schema<IUser, UserModel, IUserMethods>
Screenshot 2023-11-01 at 20 05 27

However, If we do not provide IUserMethods into a Schema generic, this becomes a Document type, as it should.

new Schema<IUser, UserModel>
or
new Schema<IUser, UserModel, {}>
Screenshot 2023-11-01 at 20 06 26

@pshaddel thanks!

Steps to Reproduce

Declare types/interfaces for document, methods and model.

interface IUser {
    firstName: string;
    lastName: string;
}

// Put all user instance methods in this interface:
interface IUserMethods {
    fullName(): string;
}

// Create a new Model type that knows about IUserMethods...
type UserModel = Model<IUser, {}, IUserMethods>;

Initialise schema with methods, but without third generic type, and observe the result.

const schema = new Schema<IUser, UserModel>(
    {
        firstName: { type: String, required: true },
        lastName: { type: String, required: true },
    },
    {
        methods: {
            fullName() {
                return this.firstName + " " + this.lastName;
            },
        },
    }
);

Initialise schema with methods and third generic type (IUserMethods), and observe the result.

const schema = new Schema<IUser, UserModel, IUserMethods>(
    {
        firstName: { type: String, required: true },
        lastName: { type: String, required: true },
    },
    {
        methods: {
            fullName() {
                return this.firstName + " " + this.lastName;
            },
        },
    }
);

Expected Behavior

Methods declared in Schema's options.methods should infer this with a right type, including provided interface for methods.

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

pshaddel commented Nov 1, 2023

@ruxxzebre Quick workaround:

If you do not pass IUserMethods to the Schema the typing is working(you are passing methods to the Model)!

const schema = new Schema<IUser, UserModel>(
    {
        firstName: { type: String, required: true },
        lastName: { type: String, required: true },
    },
    {
        methods: {
            fullName() {
                return this.firstName + " " + this.lastName;
            },
        },
    }
);

@ruxxzebre
Copy link
Contributor Author

ruxxzebre commented Nov 1, 2023

@ruxxzebre Quick workaround:

If you do not pass IUserMethods to the Schema the typing is working(you are passing methods to the Model)!

const schema = new Schema<IUser, UserModel>(
    {
        firstName: { type: String, required: true },
        lastName: { type: String, required: true },
    },
    {
        methods: {
            fullName() {
                return this.firstName + " " + this.lastName;
            },
        },
    }
);

Yes It works, as stated in ticket. However methods are not appearing in this at all.
Screenshot 2023-11-01 at 21 53 56

The thing is that it's currently not possible to have access to typings of methods from other methods (if we're not speaking of schema.method(...))

@ruxxzebre
Copy link
Contributor Author

@ruxxzebre Quick workaround:
If you do not pass IUserMethods to the Schema the typing is working(you are passing methods to the Model)!

const schema = new Schema<IUser, UserModel>(
    {
        firstName: { type: String, required: true },
        lastName: { type: String, required: true },
    },
    {
        methods: {
            fullName() {
                return this.firstName + " " + this.lastName;
            },
        },
    }
);

Yes It works, as stated in ticket. However methods are not appearing in this at all. Screenshot 2023-11-01 at 21 53 56

The thing is that it's currently not possible to have access to typings of methods from other methods (if we're not speaking of schema.method(...))

Made a workaround for my project, looks like this:

type AddThisParameter<T, Doc> = {
    [K in keyof T]: T[K] extends (...args: infer A) => infer R
        ? (this: Doc, ...args: A) => R
        : T[K];
};

type HydratedUserDocument = HydratedDocument<
    FlatRecord<IUser>,
    IUserMethods
>;

export const userSchema = new mongoose.Schema<
    IUser,
    UserModel,
    AddThisParameter<IUserMethods, HydratedUserDocument>
>(

@ruxxzebre
Copy link
Contributor Author

@pshaddel created a pull request targeted to this specific issue.
Hoping it's appropriate!

@vkarpov15 vkarpov15 modified the milestones: 7.6.5, 8.0.1 Nov 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants