-
-
Notifications
You must be signed in to change notification settings - Fork 595
Description
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
MyMixinSchemais not assignable to type
Partial<ServiceSchema<ServiceSettingSchema, Service<ServiceSettingSchema>>>
Types of propertycreatedare incompatible.Type
ServiceSyncLifecycleHandler<MyMixinThis> | ServiceSyncLifecycleHandler<MyMixinThis>[] | undefined``` is not assignable to typeServiceSyncLifecycleHandler<Service> | ServiceSyncLifecycleHandler<Service>[] | undefined`Type
ServiceSyncLifecycleHandler<MyMixinThis>is not assignable to type
ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>> | ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>>[] | undefinedType
ServiceSyncLifecycleHandler<MyMixinThis>is not assignable to type
ServiceSyncLifecycleHandler<Service<ServiceSettingSchema>>
PropertysomePropertyis missing in typeService<ServiceSettingSchema>but required in typeMyMixinThis