Skip to content

Incompatibility with recent versions of inversifyJS #1717

@helios-ag

Description

@helios-ag

Sorting

  • I'm submitting a ...

    • bug report
    • feature request
    • support request
  • I confirm that I

    • used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

If you define container configuration according to current docs

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };
and point to it in the tsoa.json as iocModule,

Container expected to be compiled

Current Behavior

If you define container configuration according to current docs

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };

and point to it in the tsoa.json as iocModule

And during build we getting error

tsoa-generated/routes.ts:622:23 - error TS2322: Type 'Container | IocContainer' is not assignable to type 'IocContainer'.
  Type 'Container' is not assignable to type 'IocContainer'.
    Types of property 'get' are incompatible.
      Type '<T>(serviceIdentifier: ServiceIdentifier<T>) => T' is not assignable to type '{ <T>(controller: { prototype: T; }): T; <T>(controller: { prototype: T; }): Promise<T>; }'.
        Types of parameters 'serviceIdentifier' and 'controller' are incompatible.
          Type '{ prototype: any; }' is not assignable to type 'ServiceIdentifier<any>'.
            Type '{ prototype: any; }' is missing the following properties from type 'Function': apply, call, bind, length, and 4 more.
                 const container: IocContainer = typeof ioc === 'function' ? (ioc as IocContainerFactory)(request) : ioc;

Possible Solution

This happens due to recent changes in the InversifyJS

Signature of export type ServiceIdentifier<T = unknown> = (string | symbol | Newable<T> | Abstract<T>);
has been changed to

https://github.com/inversify/InversifyJS/blob/master/src/interfaces/interfaces.ts#L66

that borrowed from here:

https://github.com/inversify/monorepo/blob/main/packages/container/libraries/common/src/services/models/ServiceIdentifier.ts#L3C8-L8C14

The simplest solution without doing changes to libraries itself to make wrapper, in TSyringe way:

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };
and point to it in the tsoa.json as iocModule,

Now you need to wrap it up:

import { IocContainer } from '@tsoa/runtime';
import { ioc } from './ioc';

export const iocContainer: IocContainer = {
   get: <T>(controller: { prototype: T }): T => {
      return ioc.resolve<T>(controller as never);
   },
};

And point to it in tsoa.json

Another way to fix behavior is to update signature of container definition here
https://github.com/lukeautry/tsoa/blob/master/packages/runtime/src/interfaces/iocModule.ts#L2

Context (Environment)

Version of the library: 6.5.0
Version of NodeJS: 22.11

  • Confirm you were using yarn not npm: [ ]

Detailed Description

Breaking change?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions