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

tsoa not generating when given an OR operator in response #352

Closed
oreporan opened this issue May 6, 2019 · 13 comments
Closed

tsoa not generating when given an OR operator in response #352

oreporan opened this issue May 6, 2019 · 13 comments

Comments

@oreporan
Copy link

oreporan commented May 6, 2019

When I create a controller that returns

 Promise<User | null>

The swagger generated code returns

Promise<any>

I understand that type aliases are not allowed in the response, but what is the correct syntax to allow returning null?

@oreporan
Copy link
Author

oreporan commented May 18, 2019

Any updates? Is there a maintainer for this repo?

I've also tried giving another interface

<User | NoUser> still generates Promise<any>

The issue is actually in swagger, which turns this into object

However this is dealt with here

@dgreene1
Copy link
Collaborator

@oreporan we're actively working on fixing this. There's a new issue number (#393) that we're using to track this so I'm going to close this issue. And there's already a PR out with a proposal #400. Please note that union types can not be represented in Swagger 2.0, but they can be in OpenAPI 3.0. So once PR #400 merges, you'll need change tsoa.json's "swagger"."specVersion" to be 3

@dgreene1
Copy link
Collaborator

@oreporan I'm happy to report that the we added our first draft of unions and intersections in v2.4.11. Please consider upgrading to it and let us know how it works for you. :) Please note: you must have config.swagger.specVersion set to 3 for this to work since oneOf and allOf are not supported in Swagger (but they are in OpenAPI 3.0).

I'm not 100% confident that we handled the Promise<User | null> case in a manner that you would like. But if you can't get it to work, please let us know and we can reopen this ticket. @WoH should be tagged since he understands that code best.

@js2me
Copy link

js2me commented Jan 11, 2020

Hi everyone , I've got that problem.

TSOA (v. 2.5.11) config:

{
  "swagger": {
    "basePath": "/api/v1",
    "entryFile": "./src/main.ts",
    "noImplicitAdditionalProperties": "silently-remove-extras",
    "specVersion": 3,
    "outputDirectory": ".",
    "controllerPathGlobs": ["./src/controllers/**/*.ts"]
  },
  "routes": {
    "authenticationModule": "./src/utils/authentication.ts",
    "basePath": "/api/v1",
    "entryFile": "./src/main.ts",
    "routesDir": "./src/server",
    "middleware": "express"
  }
}

Part of controller where caused exception

@Route("/jobs")
@Tags('Jobs')
export class JobsController extends Controller {

  @Get('/{id}')
  @Security("jwt")
  public async getJob(@Path('id') jobId: string): Promise<Job | null> { // here
    return getJobById(jobId);
  }
}

And that's my output:
image

@WoH
Copy link
Collaborator

WoH commented Jan 11, 2020

#479

@dgreene1
Copy link
Collaborator

Just a reminder: The workaround is to make it a union with undefined. But yes, #479 tracks the feature enhancement to allow a union with null.

@aktary
Copy link
Contributor

aktary commented May 24, 2020

I have exactly this problem, but with undefined. The workaround of making a union doesn't work either, because as soon as it sees undefined in the union, it blows up with:

Generate routes error.
 Error: Unknown type: UndefinedKeyword
At: /Users/davidaktary/Projects/singularity/projects/discovery/server/src/api/controllers/undefineable.d.ts:1:1.
This was caused by 'T | undefined'

@starikcetin
Copy link

starikcetin commented May 4, 2021

This error still persists as explained by others above. foo | null works, but foo | undefined gives Error: Unknown type: UndefinedKeyword error.

@npHavens
Copy link

I have the same error

@Nezteb
Copy link

Nezteb commented Jun 28, 2021

I'll bump this thread because I have the same issue with:

@Get("{folderId}")
public async getFolderById(@Path() folderId: string): Promise<Folder | undefined> {
  return await this.folderService?.getFolderById(folderId);
};

In this case I'm using TypeORM, and most of its functions return either an entity or undefined, not null.

@WoH
Copy link
Collaborator

WoH commented Jun 28, 2021

So what's the JSON Schema for Folder | undefined you'd want us to generate here?

@Nezteb
Copy link

Nezteb commented Jun 28, 2021

What I ended up doing was something like:

@Get("{folderId}")
public async getFolderById(@Path() folderId: string): Promise<Folder | null> {
  const result = await this.folderService?.getFolderById(folderId);
  return result === undefined ? null : result;
}

This prevents the Generate routes error. Error: Unknown type: UndefinedKeyword error, though I don't know if it's the correct way of doing things.

I'm guessing it's just a matter of undefined and null meaning the same thing as far as OpenAPI is concerned? In both cases I would expect the value being nullable (in OpenAPI v3).

@WoH
Copy link
Collaborator

WoH commented Jun 28, 2021

It's just a matter of undefined and null meaning the same thing as far as OpenAPI is concerned.

It does not mean the same thing.

E: I've elaborated in the past, maybe someone can link the comment. The TL;DR ist: you can easily translate an optional property on an object to JSON Schema but not undefined the keyword, because it may not be valid. Trying to return undefined and selling it as JSON is a pretty good example of that.

But that's enough of a devolution, stick to the relevant issues for the UndefinedKeyword errors.

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

8 participants