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

Single literal type does not work correctly #320

Closed
mattchr opened this issue Dec 10, 2018 · 8 comments · Fixed by #508
Closed

Single literal type does not work correctly #320

mattchr opened this issue Dec 10, 2018 · 8 comments · Fixed by #508

Comments

@mattchr
Copy link

mattchr commented Dec 10, 2018

interface WorksCorrectly {
  myLiteral: 'hello' | 'world';
}

interface DoesNotWork {
  myLiteral: 'hello';
}

I believe that this should produce an enum that allows a single item.

A workaround is to declare it as a typescript enum, or a string literal with two redundant values

enum SingleValueEnum {
  HELLO = 'hello',
}

interface WorkAround {
  myLiteral: SingleValueEnum;
}

interface WorkAroundUglier {
  myLiteral: 'hello' | 'hello';
}
@dgreene1
Copy link
Collaborator

New maintainer here. Sorry for the delay. I'd like to confirm your expectations. So you'd like to see something like be produced right?

definitions:
  ObjectWithOneValue:
    type: object
    properties:
      myLiteral:
        type: string
        enum:
          - hello
  ObjectWithTwoValues:
    type: object
    properties:
      myLiteral:
        type: string
        enum:
          - hello
          - world

And that's if you provided:

interface ObjectWithTwoValues {
  myLiteral: 'hello' | 'world';
}

interface ObjectWithOneValue {
  myLiteral: 'hello';
}

@marius-usvat
Copy link
Contributor

Am having this problem as well. This currently throws Error: Unknown type: LiteralType

interface ObjectWithOneValue {
  myLiteral: 'hello';
}

From what I understood from the OA Specification issue 1313 is that mattchr's described behaviour is the current workaround for specifying constants and will be reworked in OAS 3.1

Any possible workaround in the current version?

@mattchr
Copy link
Author

mattchr commented Oct 1, 2019

@dgreene1 , yes, that looks correct to me.

Sorry for the delay, I switched companies and am no longer working on this project.

@marius-usvat
Copy link
Contributor

marius-usvat commented Oct 2, 2019

@dgreene1 I tried adding the case to resolve() in typeResolver. The swagger generation worked but I have no idea how this would impact the codebase. Unfortunately don't really have time to look into it further atm 😞

if (this.typeNode.kind === ts.SyntaxKind.LiteralType) {
    return { dataType: 'enum', enums: [ this.typeNode.literal.text ] } as Tsoa.EnumerateType;
}

@WoH
Copy link
Collaborator

WoH commented Oct 2, 2019

@dgreene1 Can you add this to 3.0? I'll take a look

@dgreene1 dgreene1 added this to To do in V3 (operation type aliases) via automation Oct 2, 2019
@dgreene1
Copy link
Collaborator

dgreene1 commented Oct 2, 2019

I added it to the 3.0 branch project, but it would be really great if this could be accomplished in the current code.

@marius-usvat
Copy link
Contributor

marius-usvat commented Oct 3, 2019

I'm trying to implement discriminated union types and another thing I've noticed is even the current workaround 'hello' | 'hello' breaks this. Pulling out my example from the array metadata issue:

interface Order {
  date: Date;
  delivery: Date;
  orderLines: Array<OrderLinePurchase | OrderLineRent>;
}

interface OrderLinePurchase {
   type: 'purchase' | 'purchase';
}

interface OrderLineRent {
   type: 'rent' | 'rent';
}

With this configuration, the validation works (getting an error if the type is not purchase or rent) but the order line object passed to my controller has type: undefined.

Configuring a single type array works fine

interface Order {
  date: Date;
  delivery: Date;
  orderLines: Array<OrderLinePurchase>;
}

interface OrderLinePurchase {
   type: 'purchase' | 'purchase';
}

Order line object passed to the controller has type: 'purchase'

Though again, I might be approaching this the wrong way, please let me know! Also, would this be considered a separate issue? I wouldn't mind submitting it as such if it's the case.

@WoH
Copy link
Collaborator

WoH commented Oct 5, 2019

I added it to the 3.0 branch project, but it would be really great if this could be accomplished in the current code.

Not properly. I guess we could just patch the issue identified and move on until someone discovers the next unfortunate assumption this method makes, like filtering all type aliases, but I think that's uhm... un unfortunate decision.

Right now, getLiteralType is a very narrowly defined TA implementation. (A typealias with for multiple literalTypes). A better way would be to ref the alias and resolve the type (a union) that resolves each member, so we just have to find a representation for a single literal type that also works for a single literal type, which is the main issue in this thread.

I'd rather get a proper literal implementation that relies on resolving TypeAliases than keep patching something I'd rather rip out entirely.

In, I'd say, approximately 99% of the cases, this method would resolve something wrong or just 'any'

@WoH WoH mentioned this issue Oct 8, 2019
6 tasks
@WoH WoH moved this from To do to Review in progress in V3 (operation type aliases) Oct 9, 2019
V3 (operation type aliases) automation moved this from Review in progress to Done Oct 11, 2019
@WoH WoH moved this from Done to Beta in V3 (operation type aliases) Jan 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

4 participants