tsoa icon indicating copy to clipboard operation
tsoa copied to clipboard

Multiple matching models error only on version 3.1.0 and later

Open bengoldsh opened this issue 4 years ago • 21 comments

Sorting

  • I'm submitting a ...

    • [v] bug report
    • [ ] feature request
    • [ ] support request
  • I confirm that I

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

Expected Behavior

I upgraded tsoa from 3.0.8 lately, and i'm getting Error: Multiple matching models found for referenced type LoDashStatic; please make model names unique. All i did was include the 'Lodash' library and use it in the project. Everything works perfectly on 3.0.8 but on 3.1.0 and later (3.2.1 tested) it doesn't work anymore.

bengoldsh avatar Jun 24 '20 14:06 bengoldsh

@endor could this be related to #692?

WoH avatar Jun 24 '20 15:06 WoH

Lodash exports LoDashStatic within a namespace, so it's definitely possible that tsoa now finds that type, where before it couldn't. I'm not really sure why it would throw that error though, unless you're using Lodash types within your models. This needs some further debugging, which would be easier if you could tell us if and how you're including Lodashs types in your models. I could try to look into this soonish.

endor avatar Jun 24 '20 18:06 endor

We're having the same problem with the @kubernetes/client-node package. We tried using the ignore config so Tsoa wouldn't crawl the node_modules folder, but it doesn't seem to respect that config setting at all.

aktary avatar Jun 29 '20 19:06 aktary

ok... checking back in with an update. We had complexity because we're running a monorepo that I won't get into here, but this setting in tsconfig.json worked to get tsoa to ignore the duplicate definition in kubernetes:

"ignore": ["**/node_modules/@kubernetes/**"],

aktary avatar Jun 29 '20 20:06 aktary

@WoH I don't yet understand, why this is a bug. It's discovering duplicate definitions, that it didn't discover before. How is this supposed to be fixed? We already have documentation telling users what to do in case of duplicate definitions.

endor avatar Jul 01 '20 07:07 endor

The issue I'm seeing is that it's very much unlikely that LodashStatic is exposed for tsoa to use in the API definition. That's an assumption, until I know I shouldn't have classified this as a bug.

WoH avatar Jul 01 '20 07:07 WoH

It shouldn't be discovering anything in node_modules, should it? I can say for sure in our case that we don't want anything in node_modules exposed.

aktary avatar Jul 01 '20 15:07 aktary

Disagree. If you expose some interface from some library as a body parameter you are using that'll be in node_modules. If you use any of the TS utility types to define the response type of your controller method, guess where that's coming from? However, where I will agree is that, unless this interface has to be used to describe your API, it should not "leak". That's why I initially already labeled this a bug.

E; If you want to never expose something from node_modules, that's ok, but I'd consider it a bad default to apply. As you can remove them using tsconfig, that's kinda fine from imho.

WoH avatar Jul 01 '20 22:07 WoH

Yes, I agree that if we expose it via an interface, it should be included, but that's not the case here. One of my developers had this happen with the @kubernetes library on his branch. I installed that library on my own branch (with no Kubernetes functionality in my branch). All I had to do to trigger the error was to import the module from @kubernetes in one of my controller files. I never actually used it.

aktary avatar Jul 01 '20 23:07 aktary

I don't yet understand, why this is a bug

All I had to do to trigger the error was to import the module from @kubernetes in one of my controller files. I never actually used it.

That's not what should be happening. Thanks for confirming my suspicion. This seems to be a bug.

WoH avatar Jul 01 '20 23:07 WoH

I've tried to investigate this a bit. I couldn't reproduce it with @kubernetes/client-node, but I could reproduce it with lodash. I haven't yet figured out what the actual problem is, but it seems that Partial, which we use in our TestModel has a member called ___, and LoDashStatic seems to be a type alias for that. I hope to understand this a little better soon.

endor avatar Jul 04 '20 10:07 endor

I can share a similar experience. We have a Status interface, that, starting with the namespace patch, instead renders a Status enum from the Sentry node_modules lib.

This is the reason for the concerns I mentioned when I suggested using TS to "jump to declaration" instead of using names, which may not be unique, especially after introducing namespaces declarations into the list of candidates.

Maybe we can at least fix the check for unique declarations if multiple declarations exist (which seems to not be happening properly when a namespaced and a non-namespaced declaration of the same name exist.

WoH avatar Jul 04 '20 10:07 WoH

We can try. Otherwise we can also revert the change.

endor avatar Jul 04 '20 12:07 endor

In my case, if we throw an error and ask for @tsoaModel, that's perfect.

WoH avatar Jul 04 '20 15:07 WoH

I think that would be a nice and easy solution, but I guess in case of lodash, it doesn't really work, because there's not really a name overlapping in the models we've defined. That's why we also cannot choose the "correct" model, if we have multiple. Like say we would generally choose the one outside of a namespace or such. lodash might be a special case, but I guess it's common enough that it should be fixed somehow.

It is probably better to use TS' "jump to declaration", though I'm not aware how that works and more importantly, I probably won't have the time in the very near future to do this properly. If you could let me know some resource explaining this in more detail, I might get to it at some point.

As you say, we have a block that filters the models, should there be multiple matches. What it currently does is:

  • check for models from TS and remove those
  • check for models marked @tsoaModel and prefer those

We could add another "rule" here to prefer "local" models to ones found in node_modules, but in the case of lodash it means that there are no models left after the filtering and it just doesn't resolve Partial correctly.

It's probably good to understand why it jumps from Partial to lodash to solve this. Might get to this soonish.

endor avatar Jul 04 '20 17:07 endor

Okay, finally I have at least found the issue, and it makes somewhat more sense. lodash is having an interface called Partial defined in their namespace, so we have two competing definitions of Partial. One in lodash and one in TS. But as I said above, we filter the types defined in TS for model type declarations, so it uses the lodash one. I am not sure how that worked before introducing the namespace change, as that should have resulted in not finding anything. I guess I'll go back in git and look it up. Anyway, I wish we had better documentation, so I'd know why we filter the TS types out. But I guess it's also a more general problem, if we use two libraries defining the same thing, which we use in one of our models, there's no easy way to mark that as @tsoaModel. Or am I missing something?

endor avatar Jul 05 '20 18:07 endor

I have similar issue. One of classes has name "Stats" and it conflicts with Stats from @types/node/fs.d.ts Full error stack:

Generate swagger error.
 Error: Multiple matching models found for referenced type Stats; please make model names unique. Conflicts found: "/home/aaleksandrov/work/stream-ingester/node_modules/sdk/src/model/SurveyResponse.ts"; "/home/aaleksandrov/work/stream-ingester/node_modules/@types/node/fs.d.ts". 
 in 'SurveyResponseController.submitSurveyResponseMessage'

Worked this around by adding

"ignore": ["**/node_modules/@types/node/**"],

aaleksandrov avatar Aug 06 '20 12:08 aaleksandrov

@aaleksandrov this is the expected behavior we want here (assuming you use a Stats type/interface in one of your controllers).

WoH avatar Aug 06 '20 22:08 WoH

@WoH I don't use Stats from @types/node/fs.d.ts

aaleksandrov avatar Aug 07 '20 08:08 aaleksandrov

Hit the same issue trying to upgrade from 3.0.8: Error: Multiple matching models found for referenced type LoDashStatic

Workaround: add this to tsoa.json:

  "ignore": ["**/node_modules/@types/lodash/**"],

aldenquimby avatar Oct 16 '20 16:10 aldenquimby

I've been getting this error Error: Multiple matching models found for referenced type LoDashStatic

only when trying to make a partial interface:

export interface UpdateRenderTemplate extends Partial<CreateRenderTemplate> {}

"@tsoa/cli": "^3.8.0",

@aldenquimby your workaround didn't work, for me only rewriting partial did it:

type MyPartial<T> = {
    [P in keyof T]?: T[P];
};

oreporan avatar Jan 09 '22 13:01 oreporan