You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
First off - there are many issues dancing around this issue (I've spent half a day trying to identify the rhyme/reason for the current behavior). None, however, specifically target the typescript-node generator. The typescript-* generators share no templates, though it appears the new typescript generator has some copypasta from typescript-node.
There are two issues I'm addressing here:
Models specified using oneOf are not generated properly
ObjectSerializer does not properly handle discriminator
Point 2 is fairly self-explanatory, but I'll elaborate: the discriminator property allows for a mapping object. The current implementation assumes the discriminator property is the name of a class:
vardiscriminatorType=data[discriminatorProperty];if(typeMap[discriminatorType]){returndiscriminatorType;// use the type given in the discriminator}else{returnexpectedType;// discriminator did not map to a type}
Point 1 is a bit gnarlier. In the attached example, the class Message is generated as a superset of ALL subclass properties. This makes it a big damn mess and could lead to unexpected results in the event that subclasses define properties using the same names. If you attempt to call ObjectSerializer.deserialize(data, 'Message'), it deserializes what should be a FooMessage as a Message. If you don't care about the typing, however, the properties are all there, at least.
openapi-generator version
5.1.1, main (5.2.1-SNAPSHOT as of this writing)
OpenAPI declaration file content or url
openapi: 3.0.3info:
description: Exampleversion: '1.2.3'title: 'example'paths:
/foo:
get:
tags:
- foooperationId: getFooresponses:
'204':
description: Foocomponents:
schemas:
MessageOperation:
description: Message operationtype: stringenum:
- foo_op
- bar_opMessage:
type: objectdescription: Any message oneOf:
- $ref: '#/components/schemas/FooMessage'
- $ref: '#/components/schemas/BarMessage'discriminator:
propertyName: operationmapping:
foo_op: '#/components/schemas/FooMessage'bar_op: '#/components/schemas/BarMessage'MessageBase:
type: objectdescription: Base class for a messagerequired:
- id
- operation
- error
- timestampproperties:
id:
type: stringformat: uuiddescription: A unique ID for this messageoperation:
description: The operation to be performed$ref: '#/components/schemas/MessageOperation'error:
type: booleandefault: falsedescription: Indicates whether or not this is an error messagetimestamp:
type: stringformat: date-timedescription: The time when this message was sentFooMessage:
description: A Foo messagetype: objectallOf:
- $ref: '#/components/schemas/MessageBase'
- type: objectrequired:
- fooproperties:
foo:
type: stringBarMessage:
description: A Bar messagetype: objectallOf:
- $ref: '#/components/schemas/MessageBase'
- type: objectrequired:
- barproperties:
bar:
type: string
Generate a typedef for so-called tagged union types. The typescript-axios generator does this currently, and I believe it results in much cleaner generated code. Depending on how people use the generated code, this will be a breaking change (if anyone is using the base class).
Encapsulate the contents of the discriminator.mapping into ObjectSerializer to allow deserializing an e.g. Message into FooMessage or BarMessage, as determined by the value of discriminator. The current behavior can be kept as a fallback.
I'm currently working on a PR for these but would like some feedback from the TS team. :)
As I'm working through this, I've found a corner case here...
If a model uses oneOf AND specifies properties, it is not a true tagged union. I'm not sure how to treat this case - I think it is valid, as per the OAPI spec, but it doesn't make any sense to me to do this. Could handle it in a couple ways:
generate a typedef and duplicate the common properties to each of the sub models
generate the base with just its properties and also generate a typedef i.e. BaseType which would then resemble: const type BaseType = (Foo & Base) | (Bar & Base);
Bug Report Checklist
Description
First off - there are many issues dancing around this issue (I've spent half a day trying to identify the rhyme/reason for the current behavior). None, however, specifically target the
typescript-node
generator. Thetypescript-*
generators share no templates, though it appears the newtypescript
generator has some copypasta fromtypescript-node
.There are two issues I'm addressing here:
oneOf
are not generated properlyObjectSerializer
does not properly handlediscriminator
Point 2 is fairly self-explanatory, but I'll elaborate: the
discriminator
property allows for amapping
object. The current implementation assumes thediscriminator
property is the name of a class:Point 1 is a bit gnarlier. In the attached example, the class
Message
is generated as a superset of ALL subclass properties. This makes it a big damn mess and could lead to unexpected results in the event that subclasses define properties using the same names. If you attempt to callObjectSerializer.deserialize(data, 'Message')
, it deserializes what should be aFooMessage
as aMessage
. If you don't care about the typing, however, the properties are all there, at least.openapi-generator version
5.1.1
,main
(5.2.1-SNAPSHOT
as of this writing)OpenAPI declaration file content or url
Generation Details
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g typescript-node -i ./poly.yaml -o tmp/
Steps to reproduce
Generate code
Related issues/PRs
#6376 #9305 #4374 #15 #10017 #6513
Suggest a fix
My proposed solution here is two-fold:
typedef
for so-called tagged union types. Thetypescript-axios
generator does this currently, and I believe it results in much cleaner generated code. Depending on how people use the generated code, this will be a breaking change (if anyone is using the base class).discriminator.mapping
intoObjectSerializer
to allow deserializing an e.g.Message
intoFooMessage
orBarMessage
, as determined by the value ofdiscriminator
. The current behavior can be kept as a fallback.I'm currently working on a PR for these but would like some feedback from the TS team. :)
CC @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02)
The text was updated successfully, but these errors were encountered: