Skip to content

Mixins array does not accept schemas with lifecycle handlers that define their own "this" type #1321

@marceliwac

Description

@marceliwac

Current Behavior

When defining a service using TypeScript, the service schema consists of two generic types that can be provided to facilitate support for typed "this" across actions, methods and lifecycle handlers:

interface MySettings extends ServiceSettingSchema {
	myValue: number;
}

interface MyMethods {
	myMethod: (this: MyThis) => void;
}

interface MyThis  extends Service<MySettings> {
	someProperty: string;
}

interface MySchema extends ServiceSchema<MySettings, MyThis> {}

const myServiceSchema: MySchema = {
	name: 'myService',
	actions: {
		myAction(this: MyThis) {
			this.myMethod();  // myMethod is correctly identified, because this type contains it in its definition
		}
	},
	methods: {
		myMethod(this: MyThis) {
			// ...
		}
	},
	started(this: MyThis) {
		// ...
	}
}

However, if we apply the same approach to a mixin that also utilises typed "this":

interface MyMixinSettings extends ServiceSettingSchema {
	myMixinSetting: number;
}

interface MyMixinThisExtension {
	someProperty: string;
}

interface MyMixinThis extends Service<MyMixinSettings>, MyMixinThisExtension {}

interface MyMixinSchema extends ServiceSchema<MyMixinSettings, MyMixinThis> {}

const myMixin: MyMixinSchema = {
	name: '',
	started(this: MyMixinThis) {
		// ...
	}
}

That mixin cannot be used inside the mixins array of MyService, because ServiceSchema defines mixins as Partial<ServiceSchema>[] (expands to: Partial<ServiceSchema<ServiceSettingSchema>>), and is therefore not compatible with MyMixinSchema (expands to: ServiceSchema<MyMixinSettings, MyMixinThis>).

interface MySettings extends MyMixinSettings, ServiceSettingSchema {
	myValue: number;
}

interface MyMethods {
	myMethod: (this: MyThis) => void;
}

interface MyThis extends MyMixinThisExtension, Service<MySettings> {
	someProperty: string;
}

interface MySchema extends ServiceSchema<MySettings, MyThis> {}

const myServiceSchema: MySchema = {
	name: 'myService',
	mixins: [myMixin], // Typescript error is thrown here
	actions: {
		myAction(this: MyThis) {
			this.myMethod(); 
		}
	},
	methods: {
		myMethod(this: MyThis) {
			// ...
		}
	},
	started(this: MyThis) {
		// ...
	}
}

Expected Behavior

Service should accept mixins that define their own ServiceSettingSchema and this types.

Failure Information

The problem boils down to the type of mixins property in ServiceSchema definition. This type should either ignore the specific ServiceSettingSchema and this types, or provide some mechanism for specifying their requirements (I don't know if this is possible, or at least how it could be achieved). The following adjustment resolves the issue:

interface ServiceSchema<S = ServiceSettingSchema, T = Service<S>> {
  // ...
  mixins?: Partial<ServiceSchema<any, any>>[];
  // ...                          ^----^---- this resolves the problem
}

Steps to Reproduce

Use the above example with moleculer module installed. Typescript error will be indicated by the editor (and during compilation).

Context

  • Moleculer version: 0.14.35
  • NodeJS version: 20.15.0
  • Operating System: MacOS

Failure Logs

TypeScript error

TS2322: Type MyMixinSchema is not assignable to type
Partial<ServiceSchema<ServiceSettingSchema, Service<ServiceSettingSchema>>>
Types of property created are incompatible.

Type
ServiceSyncLifecycleHandler<MyMixinThis> | ServiceSyncLifecycleHandler<MyMixinThis>[] | undefined``` is not assignable to type ServiceSyncLifecycleHandler<Service> | ServiceSyncLifecycleHandler<Service>[] | undefined`

Type ServiceSyncLifecycleHandler<MyMixinThis> is not assignable to type
ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>> | ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>>[] | undefined

Type ServiceSyncLifecycleHandler<MyMixinThis> is not assignable to type
ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>>
Property someProperty is missing in type Service<ServiceSettingSchema> but required in type MyMixinThis

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions