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

[resolved but might be handles better?] Generic controller's methods #1510

Closed
3 of 4 tasks
gdelory opened this issue Nov 10, 2023 · 3 comments
Closed
3 of 4 tasks

[resolved but might be handles better?] Generic controller's methods #1510

gdelory opened this issue Nov 10, 2023 · 3 comments

Comments

@gdelory
Copy link

gdelory commented Nov 10, 2023

Hi all, I thought I would open a bug, then saw that what I was trying to do simply doesn't exist in OpenApi doc (here). To save some time to others, and because I searched the issues and there is nothing about generic controller's methods, I thought I would sill open/close this issue so other can find it 😉

I was trying to migrate some basic express code we had which returns different types based on a query param. I could make the return type a union of both types, of course. But I tried to be smart and apply condition return type like I usually do with other normal (none tsoa) functions.

import { Controller, Get, Query, Route } from 'tsoa'

export type ConditionalQueryParam = 'true' | 'false' | undefined
export type Entry = { name: string }
export type ConditionalReturn<ID extends ConditionalQueryParam> = ID extends 'true' ? Entry[] : Entry

@Route('test')
export class TestController extends Controller {

  @Get('/')
  async get<MultipleParam extends ConditionalQueryParam>(
    @Query() multipleResults?: MultipleParam
  ): Promise<ConditionalReturn<MultipleParam>> {
    if (multipleResults == 'true') {
      return [{ name: 'multiple entry result '}] as ConditionalReturn<MultipleParam>
    } else {
      return { name: 'single entry result '} as ConditionalReturn<MultipleParam>
    }
  }
}

And this fails with the following error:

$ npm run build-api

> [email protected] build-api
> rm -rf src/routes.ts && tsoa spec-and-routes

Generate routes error.
 GenerateMetadataError: No matching model found for referenced type MultipleParam. 
 in 'TestController.get'
    at /home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/methodGenerator.js:76:23
    at Array.map (<anonymous>)
    at MethodGenerator.buildParameters (/home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/methodGenerator.js:69:14)
    at MethodGenerator.Generate (/home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/methodGenerator.js:43:33)
    at /home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/controllerGenerator.js:46:41
    at Array.map (<anonymous>)
    at ControllerGenerator.buildMethods (/home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/controllerGenerator.js:46:14)
    at ControllerGenerator.Generate (/home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/controllerGenerator.js:35:27)
    at /home/gui/wfm/node_modules/@tsoa/cli/dist/metadataGeneration/metadataGenerator.js:191:41
    at Array.map (<anonymous>

Maybe instead of crashing, it would be possible to create a union type and output an anyOf in the swagger doc?

Anyway, if anyone encounter this, since openapi doesn't support it, it's just easier to switch back to a union type:

Promise<Entry | Entry[]>
  • 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
Copy link

Hello there gdelory 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

@WoH
Copy link
Collaborator

WoH commented Nov 25, 2023

I think this can not really be well documented via OpenAPI either way.
From a pure TS perspective, generic is fine here, but to compile down into a spec, the union is what you want.

So, in short, this is the best way right now.

@gdelory
Copy link
Author

gdelory commented Dec 4, 2023

@WoH I completely agree with you, I just opened this issue to save time to future users having the same issue. In short, don't use conditional return type since it doesn't make sense (doesn't exist) anyway with OpenAPI, just stick to a union type for the return.

Closing this. Sorry, I should have done so right away, this was more meant as documentation for others 😉 Thanks a lot for taking the time to answer, and your library is awesome, we had a really good experience with it so far, and I'll be happy to try to contribute if I have the opportunity in the future.

@gdelory gdelory closed this as completed Dec 4, 2023
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

No branches or pull requests

2 participants