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

[typescript-fetch] correct oneOf model to or not concat when handling enums #10017

Closed
wants to merge 17 commits into from
3 changes: 3 additions & 0 deletions bin/configs/typescript-fetch-one-of.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
generatorName: typescript-fetch
outputDir: samples/client/petstore/typescript-fetch/builds/one-of
inputSpec: modules/openapi-generator/src/test/resources/3_0/typescript-fetch/one-of.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{{>modelEnumInterfaces}}

export function {{classname}}FromJSON(json: any): {{classname}} {
export function {{classname}}FromJSON(json: any): {{classname}} | null {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is gonna be a breaking change. if an enum property is marked as required / non-nullable in the spec, all consumers expect that it's defined.
after this change some apps will likely stop compiling.

why do yo need it anyway? you can keep the original code here - return the enum value as is, without any processing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript gave a me a warning about the implicit return null. I believe it can be removed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's because this PR changed the code inside the function, narrowing down json type to null before returning it

Copy link
Author

@prince-chrismc prince-chrismc Aug 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Playing around with this more... it previously returned a value that was not valid. so if you passed 7 and your enum was [0, 1, 2] you would get back 7 which is not the right type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, we trust the api response matches the spec. otherwise the code is gonna break anyway, since we don't do full shape verification

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The challenge is older clients being used with newer backends which just weren't aware of the existence of such values

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say, null is as unexpected as a bogus enum value (if the property is not marked as nullable).
Again, i honestly believe it's way out of scope of the generated api client.

if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values({{classname}}).includes(json as {{classname}})) {
return null;
}
Comment on lines +4 to +9
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these runtime checks allowed?

return {{classname}}FromJSONTyped(json, false);
}

export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} {
export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} | null {
return json as {{classname}};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
}
{{/discriminator}}
{{^discriminator}}
return { {{#oneOf}}...{{{.}}}FromJSONTyped(json, true){{^-last}}, {{/-last}}{{/oneOf}} };
return {{#oneOf}}{{{.}}}FromJSONTyped(json, true){{^-last}} || {{/-last}}{{/oneOf}};
prince-chrismc marked this conversation as resolved.
Show resolved Hide resolved
{{/discriminator}}
}

Expand All @@ -53,6 +53,6 @@ export function {{classname}}ToJSON(value?: {{classname}} | null): any {
}
{{/discriminator}}
{{^discriminator}}
return { {{#oneOf}}...{{{.}}}ToJSON(value){{^-last}}, {{/-last}}{{/oneOf}} };
return {{#oneOf}}{{{.}}}ToJSON(value as {{{.}}}){{^-last}} ?? {{/-last}}{{/oneOf}};
{{/discriminator}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,35 @@ components:
- one
- two
- three
StringEnumTwo:
type: string
enum:
- twoone
- twotwo
- twothree
StringOneOf:
type: string
oneOf:
- $ref: "#/components/schemas/StringEnum"
- $ref: "#/components/schemas/StringEnumTwo"
NumberEnum:
type: number
enum:
- 0
- 1
- 2
- 3
NumberEnumTwo:
type: number
enum:
- 4
- 5
- 6
NumberOneOf:
type: number
oneOf:
- $ref: "#/components/schemas/NumberEnum"
- $ref: "#/components/schemas/NumberEnumTwo"
EnumPatternObject:
type: object
properties:
Expand All @@ -227,3 +250,15 @@ components:
nullable: true
allOf:
- $ref: "#/components/schemas/NumberEnum"
ObjectOneOfEnum:
type: "object"
properties:
combined-string-enum:
oneOf:
- $ref: '#/components/schemas/StringEnum'
- $ref: '#/components/schemas/StringEnumTwo'
ObjectCombinedEnum:
type: "object"
properties:
combined-string-enum:
$ref: '#/components/schemas/StringOneOf'
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
openapi: 3.0.0
info:
version: 1.0.0
title: Enum test
servers:
- url: http://localhost:3000
paths:
/fake/enum-request-ref:
get:
operationId: fake-enum-request-get-ref
responses:
200:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PatternObject'
post:
operationId: fake-enum-request-post-ref
responses:
200:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PatternObject'
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/PatternObject"
components:
schemas:
PatternObject:
type: object
properties:
string:
type: string
nullable-string:
nullable: true
type: string
number-enum:
type: number
PatternObjectTwo:
type: object
properties:
boolean:
type: boolean
PropertyCombinedOneOf:
type: "object"
properties:
combined-string-enum:
oneOf:
- $ref: '#/components/schemas/PatternObject'
- $ref: '#/components/schemas/PatternObjectTwo'
ObjectCombinedOneOf:
oneOf:
- $ref: '#/components/schemas/PatternObject'
- $ref: '#/components/schemas/PatternObjectTwo'
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface Capitalization {
sCAETHFlowPoints?: string;
/**
* Name of the pet

* @type {string}
* @memberof Capitalization
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ export enum EnumClass {
Xyz = '(xyz)'
}

export function EnumClassFromJSON(json: any): EnumClass {
export function EnumClassFromJSON(json: any): EnumClass | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(EnumClass).includes(json as EnumClass)) {
return null;
}
return EnumClassFromJSONTyped(json, false);
}

export function EnumClassFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnumClass {
export function EnumClassFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnumClass | null {
return json as EnumClass;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ export enum OuterEnum {
Delivered = 'delivered'
}

export function OuterEnumFromJSON(json: any): OuterEnum {
export function OuterEnumFromJSON(json: any): OuterEnum | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(OuterEnum).includes(json as OuterEnum)) {
return null;
}
return OuterEnumFromJSONTyped(json, false);
}

export function OuterEnumFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnum {
export function OuterEnumFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnum | null {
return json as OuterEnum;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ export enum OuterEnumDefaultValue {
Delivered = 'delivered'
}

export function OuterEnumDefaultValueFromJSON(json: any): OuterEnumDefaultValue {
export function OuterEnumDefaultValueFromJSON(json: any): OuterEnumDefaultValue | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(OuterEnumDefaultValue).includes(json as OuterEnumDefaultValue)) {
return null;
}
return OuterEnumDefaultValueFromJSONTyped(json, false);
}

export function OuterEnumDefaultValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumDefaultValue {
export function OuterEnumDefaultValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumDefaultValue | null {
return json as OuterEnumDefaultValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ export enum OuterEnumInteger {
NUMBER_2 = 2
}

export function OuterEnumIntegerFromJSON(json: any): OuterEnumInteger {
export function OuterEnumIntegerFromJSON(json: any): OuterEnumInteger | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(OuterEnumInteger).includes(json as OuterEnumInteger)) {
return null;
}
return OuterEnumIntegerFromJSONTyped(json, false);
}

export function OuterEnumIntegerFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumInteger {
export function OuterEnumIntegerFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumInteger | null {
return json as OuterEnumInteger;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ export enum OuterEnumIntegerDefaultValue {
NUMBER_2 = 2
}

export function OuterEnumIntegerDefaultValueFromJSON(json: any): OuterEnumIntegerDefaultValue {
export function OuterEnumIntegerDefaultValueFromJSON(json: any): OuterEnumIntegerDefaultValue | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(OuterEnumIntegerDefaultValue).includes(json as OuterEnumIntegerDefaultValue)) {
return null;
}
return OuterEnumIntegerDefaultValueFromJSONTyped(json, false);
}

export function OuterEnumIntegerDefaultValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumIntegerDefaultValue {
export function OuterEnumIntegerDefaultValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): OuterEnumIntegerDefaultValue | null {
return json as OuterEnumIntegerDefaultValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ models/EnumPatternObject.ts
models/InlineObject.ts
models/InlineResponse200.ts
models/NumberEnum.ts
models/NumberEnumTwo.ts
models/NumberOneOf.ts
models/ObjectCombinedEnum.ts
models/ObjectOneOfEnum.ts
models/StringEnum.ts
models/StringEnumTwo.ts
models/StringOneOf.ts
models/index.ts
runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,23 @@
* @enum {string}
*/
export enum NumberEnum {
NUMBER_0 = 0,
NUMBER_1 = 1,
NUMBER_2 = 2,
NUMBER_3 = 3
}

export function NumberEnumFromJSON(json: any): NumberEnum {
export function NumberEnumFromJSON(json: any): NumberEnum | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(NumberEnum).includes(json as NumberEnum)) {
return null;
}
return NumberEnumFromJSONTyped(json, false);
}

export function NumberEnumFromJSONTyped(json: any, ignoreDiscriminator: boolean): NumberEnum {
export function NumberEnumFromJSONTyped(json: any, ignoreDiscriminator: boolean): NumberEnum | null {
return json as NumberEnum;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* tslint:disable */
/* eslint-disable */
/**
* Enum test
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

/**
*
* @export
* @enum {string}
*/
export enum NumberEnumTwo {
NUMBER_4 = 4,
NUMBER_5 = 5,
NUMBER_6 = 6
}

export function NumberEnumTwoFromJSON(json: any): NumberEnumTwo | null {
if ((json === undefined) || (json === null)) {
return json;
}
if(!Object.values(NumberEnumTwo).includes(json as NumberEnumTwo)) {
return null;
}
return NumberEnumTwoFromJSONTyped(json, false);
}

export function NumberEnumTwoFromJSONTyped(json: any, ignoreDiscriminator: boolean): NumberEnumTwo | null {
return json as NumberEnumTwo;
}

export function NumberEnumTwoToJSON(value?: NumberEnumTwo | null): any {
return value as any;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* tslint:disable */
/* eslint-disable */
/**
* Enum test
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

import {
NumberEnum,
NumberEnumTwo,
NumberEnumFromJSONTyped,
NumberEnumToJSON,
NumberEnumTwoFromJSONTyped,
NumberEnumTwoToJSON,
} from './';

/**
* @type NumberOneOf
*
* @export
*/
export type NumberOneOf = NumberEnum | NumberEnumTwo;

export function NumberOneOfFromJSON(json: any): NumberOneOf {
return NumberOneOfFromJSONTyped(json, false);
}

export function NumberOneOfFromJSONTyped(json: any, ignoreDiscriminator: boolean): NumberOneOf {
if ((json === undefined) || (json === null)) {
return json;
}
return NumberEnumFromJSONTyped(json, true) || NumberEnumTwoFromJSONTyped(json, true);
}

export function NumberOneOfToJSON(value?: NumberOneOf | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return NumberEnumToJSON(value as NumberEnum) ?? NumberEnumTwoToJSON(value as NumberEnumTwo);
}

Loading