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

added service type as generic type argument #1291

Open
wants to merge 4 commits into
base: next
Choose a base branch
from

Conversation

prasadmadanayake
Copy link

@prasadmadanayake prasadmadanayake commented Jun 12, 2024

Added service type as generic type argument

📝 Description

updated this type definitions for

  • service actions
  • service events
  • lifecycle events
  • service methods
    Now we can properly define custom properties in service interface like
    export interface IMySettings extends ServiceSettingSchema{}

    export interface IMyService extends Service<IMySettings>{
        custom: string
    }

    export class MyService implements Partial<ServiceSchema<IMySettings, IMyService>>{
        name: string = ""
        actions: ServiceActionsSchema<IMySettings, IMyService> = {
            "aa":{
                async handler(cy){
                    console.log(this.custom) // this resolves type correctly
                }

            }

        }
    }

💎 Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

📜 Example code

    export interface IMySettings extends ServiceSettingSchema{}

    export interface IMyService extends Service<IMySettings>{
        custom: string
    }

    export class MyService implements Partial<ServiceSchema<IMySettings, IMyService>>{
        name: string = ""
        actions: ServiceActionsSchema<IMySettings, IMyService> = {
            "aa":{
                async handler(cy){
                    console.log(this.custom)
                }
            }
        }
        methods: ServiceMethods<IMySettings, IMyService> = {
              async a2(){
                  console.log(this.custom)  
              }
        }

        events: EventSchemas<IMySettings, IMyService> = {
            "a3":{
                async handler(cy){
                    console.log(this.custom)
                }
            }
        }

    }

🚦 How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • manually tested with typescript project. no breaking changes with type definition files.

🏁 Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code

@ccampanale
Copy link

I like this idea. We've created and used custom types this way in our system for years but since upgrading to moleculer@0.14.26 we have type errors in all packages. As it exists, refactoring would be huge adjustment (effectively moving all custom service members to module members) but something like this would definitely make this a much smaller effort while being able to once again benefit from our type checking for custom service properties. I'm all for a change like this.

@icebob icebob requested review from shawnmcknight and icebob July 28, 2024 11:10
@shawnmcknight
Copy link
Member

I'm having some trouble understanding how the example works. This is creating a new class, but that class doesn't extend the base Service class which I don't believe would work with moleculer-runner. I suppose if this class was instantiated manually and passed to broker.createService() it would just think it was a service schema object, but I'm not seeing anything in the createService workflow which would copy extra properties to the Service instance.

I might be missing something, but I don't see how that custom property would be available at runtime. Can you fill in the blanks for me?

@prasadmadanayake
Copy link
Author

Sorry for the confusion with the example. This is just the type declaration extension for service schema. Implementation will be the same as in moleculer service schema implementation. So we need to set the custom property in created lifecycle hook.


export interface IMySettings extends ServiceSettingSchema{}

export interface IMyService extends Service<IMySettings>{
    custom: string
}

export class MyService implements Partial<ServiceSchema<IMySettings, IMyService>>{
    name: string = ""
    actions: ServiceActionsSchema<IMySettings, IMyService> = {
        "aa":{
            async handler(ctx){
                console.log(this.custom) // this resolves type correctly
            }

        }

    }
    created = function(this: IMyService){
        this.custom = "initialized"
        
    }
}

@shawnmcknight
Copy link
Member

I have a couple of high-level thoughts with regards to this PR:

  1. It seems like the S generic which is used for for the settings schema is no longer really valuable since it would be available on the service type. If you're already supplying the Service type that just means the consumer needs to specify both things while the settings can be inferred from the Service. Since this is the next branch, it seems like now would be a good time to introduce a breaking change to these types.
  2. For these generics where Service is the default value, it seems like there should be a constraint applied to ensure the generic value is Service. I can't think of a scenario where you'd want to allow someone to specify a type that wasn't constrained by Service.
  3. It would be good to use a more descriptive generic than T for these service generics. Generally, I prefer to see generics using a T prefix with a more meaningful name behind it -- in this case something like TService.
  4. The formatting (spacing, etc.) is inconsistent in this PR. Please make sure to let prettier autofix this formatting for consistency purposes.

Copy link
Member

@icebob icebob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do Shawn's suggestions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants