Skip to content

Commit 7510e6b

Browse files
[Typescript] Generate oneOf schemas as type unions (OpenAPITools#19494)
* Add oneOf model for Typescript generator * Update import procces: For oneOfs only import $refs within the oneOf * Remove new line after description * Update samples * Typescript: Update model.mustache * Typescript: Remove emun from oneOf models * Update samples * Typescript oneOf: add discriminator and update deserialize procces * Typescript: update tests * Typescript oneOf: move type mapping to models * Typescript: Update samples * Typescript: Update type of mappig * Typescript: Update type of mappig * Typescript oneOf: update deserializing logic * Typescript: Update samples * Revert "[typescript] fix: `enum` can not receive stringified class name (OpenAPITools#19481)" This reverts commit 4238f17. * [typescript] chore: update fixtures --------- Co-authored-by: ksvirkou-hubspot <[email protected]>
1 parent 1518237 commit 7510e6b

File tree

91 files changed

+231
-1723
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+231
-1723
lines changed

bin/configs/typescript-consolidated-enums.yaml

-9
This file was deleted.

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java

+10
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,16 @@ public ModelsMap postProcessModels(ModelsMap objs) {
354354
}
355355
}
356356
}
357+
if (!cm.oneOf.isEmpty()) {
358+
// For oneOfs only import $refs within the oneOf
359+
TreeSet<String> oneOfRefs = new TreeSet<>();
360+
for (String im : cm.imports) {
361+
if (cm.oneOf.contains(im)) {
362+
oneOfRefs.add(im);
363+
}
364+
}
365+
cm.imports = oneOfRefs;
366+
}
357367
}
358368
for (ModelMap mo : models) {
359369
CodegenModel cm = mo.getModel();

modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export * from '{{{ importPath }}}{{importFileExtension}}';
66

77
{{#models}}
88
{{#model}}
9-
import { {{classname}}{{#hasEnums}}{{#vars}}{{#isEnum}}, {{classname}}{{enumName}} {{/isEnum}} {{/vars}}{{/hasEnums}} } from '{{{ importPath }}}{{importFileExtension}}';
9+
import { {{classname}}{{#oneOf}}{{#-first}}Class{{/-first}}{{/oneOf}}{{^oneOf}}{{#hasEnums}}{{#vars}}{{#isEnum}}, {{classname}}{{enumName}} {{/isEnum}} {{/vars}}{{/hasEnums}}{{/oneOf}} } from '{{{ importPath }}}{{importFileExtension}}';
1010
{{/model}}
1111
{{/models}}
1212

@@ -43,7 +43,7 @@ let typeMap: {[index: string]: any} = {
4343
{{#models}}
4444
{{#model}}
4545
{{^isEnum}}
46-
"{{classname}}": {{classname}},
46+
"{{classname}}": {{classname}}{{#oneOf}}{{#-first}}Class{{/-first}}{{/oneOf}},
4747
{{/isEnum}}
4848
{{/model}}
4949
{{/models}}
@@ -125,8 +125,11 @@ export class ObjectSerializer {
125125
} else {
126126
if (data[discriminatorProperty]) {
127127
var discriminatorType = data[discriminatorProperty];
128-
if(typeMap[discriminatorType]){
129-
return discriminatorType; // use the type given in the discriminator
128+
let mapping = typeMap[expectedType].mapping;
129+
if (mapping != undefined && mapping[discriminatorType]) {
130+
return mapping[discriminatorType]; // use the type given in the discriminator
131+
} else if(typeMap[discriminatorType]) {
132+
return discriminatorType;
130133
} else {
131134
return expectedType; // discriminator did not map to a type
132135
}

modules/openapi-generator/src/main/resources/typescript/model/model.mustache

+17-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import { HttpFile } from '../http/http{{importFileExtension}}';
1212
*/
1313
{{/description}}
1414
{{^isEnum}}
15+
{{#oneOf}}
16+
{{#-first}}{{>model/modelOneOf}}{{/-first}}
17+
{{/oneOf}}
18+
{{^oneOf}}
1519
export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{
1620
{{#vars}}
1721
{{#description}}
@@ -28,6 +32,18 @@ export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{
2832
{{^discriminator}}
2933
static readonly discriminator: string | undefined = undefined;
3034
{{/discriminator}}
35+
{{#hasDiscriminatorWithNonEmptyMapping}}
36+
37+
static readonly mapping: {[index: string]: string} | undefined = {
38+
{{#discriminator.mappedModels}}
39+
"{{mappingName}}": "{{modelName}}",
40+
{{/discriminator.mappedModels}}
41+
};
42+
{{/hasDiscriminatorWithNonEmptyMapping}}
43+
{{^hasDiscriminatorWithNonEmptyMapping}}
44+
45+
static readonly mapping: {[index: string]: string} | undefined = undefined;
46+
{{/hasDiscriminatorWithNonEmptyMapping}}
3147

3248
{{^isArray}}
3349
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
@@ -62,13 +78,10 @@ export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{
6278
{{/discriminatorValue}}
6379
{{/allVars}}
6480
{{#discriminatorName}}
65-
{{^discriminator.isEnum}}
6681
this.{{discriminatorName}} = "{{classname}}";
67-
{{/discriminator.isEnum}}
6882
{{/discriminatorName}}
6983
}
7084
}
71-
7285
{{#hasEnums}}
7386

7487
{{#vars}}
@@ -84,6 +97,7 @@ export enum {{classname}}{{enumName}} {
8497
{{/vars}}
8598

8699
{{/hasEnums}}
100+
{{/oneOf}}
87101
{{/isEnum}}
88102
{{#isEnum}}
89103
export enum {{classname}} {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{{#hasImports}}
2+
import {
3+
{{#imports}}
4+
{{{.}}}{{importFileExtension}},
5+
{{/imports}}
6+
} from './';
7+
8+
{{/hasImports}}
9+
/**
10+
* @type {{classname}}
11+
* Type
12+
* @export
13+
*/
14+
export type {{classname}} = {{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}};
15+
16+
/**
17+
* @type {{classname}}Class{{#description}}
18+
* {{{.}}}{{/description}}
19+
* @export
20+
*/
21+
export class {{classname}}Class {
22+
{{#discriminator}}
23+
static readonly discriminator: string | undefined = "{{discriminatorName}}";
24+
{{/discriminator}}
25+
{{^discriminator}}
26+
static readonly discriminator: string | undefined = undefined;
27+
{{/discriminator}}
28+
{{#hasDiscriminatorWithNonEmptyMapping}}
29+
30+
static readonly mapping: {[index: string]: string} | undefined = {
31+
{{#discriminator.mappedModels}}
32+
"{{mappingName}}": "{{modelName}}",
33+
{{/discriminator.mappedModels}}
34+
};
35+
{{/hasDiscriminatorWithNonEmptyMapping}}
36+
{{^hasDiscriminatorWithNonEmptyMapping}}
37+
38+
static readonly mapping: {[index: string]: string} | undefined = undefined;
39+
{{/hasDiscriminatorWithNonEmptyMapping}}
40+
}

modules/openapi-generator/src/test/resources/3_0/enum_mapping_test.yaml

-77
This file was deleted.

samples/client/others/typescript/builds/with-unique-items/models/ObjectSerializer.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@ export class ObjectSerializer {
9797
} else {
9898
if (data[discriminatorProperty]) {
9999
var discriminatorType = data[discriminatorProperty];
100-
if(typeMap[discriminatorType]){
101-
return discriminatorType; // use the type given in the discriminator
100+
let mapping = typeMap[expectedType].mapping;
101+
if (mapping != undefined && mapping[discriminatorType]) {
102+
return mapping[discriminatorType]; // use the type given in the discriminator
103+
} else if(typeMap[discriminatorType]) {
104+
return discriminatorType;
102105
} else {
103106
return expectedType; // discriminator did not map to a type
104107
}

samples/client/others/typescript/builds/with-unique-items/models/Response.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export class Response {
1818

1919
static readonly discriminator: string | undefined = undefined;
2020

21+
static readonly mapping: {[index: string]: string} | undefined = undefined;
22+
2123
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2224
{
2325
"name": "nonUniqueArray",
@@ -39,4 +41,3 @@ export class Response {
3941
public constructor() {
4042
}
4143
}
42-

samples/openapi3/client/petstore/typescript/builds/browser/models/ApiResponse.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export class ApiResponse {
2222

2323
static readonly discriminator: string | undefined = undefined;
2424

25+
static readonly mapping: {[index: string]: string} | undefined = undefined;
26+
2527
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2628
{
2729
"name": "code",
@@ -49,4 +51,3 @@ export class ApiResponse {
4951
public constructor() {
5052
}
5153
}
52-

samples/openapi3/client/petstore/typescript/builds/browser/models/Category.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export class Category {
2121

2222
static readonly discriminator: string | undefined = undefined;
2323

24+
static readonly mapping: {[index: string]: string} | undefined = undefined;
25+
2426
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2527
{
2628
"name": "id",
@@ -42,4 +44,3 @@ export class Category {
4244
public constructor() {
4345
}
4446
}
45-

samples/openapi3/client/petstore/typescript/builds/browser/models/ObjectSerializer.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ export class ObjectSerializer {
114114
} else {
115115
if (data[discriminatorProperty]) {
116116
var discriminatorType = data[discriminatorProperty];
117-
if(typeMap[discriminatorType]){
118-
return discriminatorType; // use the type given in the discriminator
117+
let mapping = typeMap[expectedType].mapping;
118+
if (mapping != undefined && mapping[discriminatorType]) {
119+
return mapping[discriminatorType]; // use the type given in the discriminator
120+
} else if(typeMap[discriminatorType]) {
121+
return discriminatorType;
119122
} else {
120123
return expectedType; // discriminator did not map to a type
121124
}

samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export class Order {
2828

2929
static readonly discriminator: string | undefined = undefined;
3030

31+
static readonly mapping: {[index: string]: string} | undefined = undefined;
32+
3133
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
3234
{
3335
"name": "id",
@@ -74,7 +76,6 @@ export class Order {
7476
}
7577
}
7678

77-
7879
export enum OrderStatusEnum {
7980
Placed = 'placed',
8081
Approved = 'approved',

samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export class Pet {
3030

3131
static readonly discriminator: string | undefined = undefined;
3232

33+
static readonly mapping: {[index: string]: string} | undefined = undefined;
34+
3335
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
3436
{
3537
"name": "id",
@@ -76,7 +78,6 @@ export class Pet {
7678
}
7779
}
7880

79-
8081
export enum PetStatusEnum {
8182
Available = 'available',
8283
Pending = 'pending',

samples/openapi3/client/petstore/typescript/builds/browser/models/Tag.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export class Tag {
2121

2222
static readonly discriminator: string | undefined = undefined;
2323

24+
static readonly mapping: {[index: string]: string} | undefined = undefined;
25+
2426
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2527
{
2628
"name": "id",
@@ -42,4 +44,3 @@ export class Tag {
4244
public constructor() {
4345
}
4446
}
45-

samples/openapi3/client/petstore/typescript/builds/browser/models/User.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export class User {
3030

3131
static readonly discriminator: string | undefined = undefined;
3232

33+
static readonly mapping: {[index: string]: string} | undefined = undefined;
34+
3335
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
3436
{
3537
"name": "id",
@@ -87,4 +89,3 @@ export class User {
8789
public constructor() {
8890
}
8991
}
90-

samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Cat.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export class Cat {
1818

1919
static readonly discriminator: string | undefined = undefined;
2020

21+
static readonly mapping: {[index: string]: string} | undefined = undefined;
22+
2123
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2224
{
2325
"name": "hunts",
@@ -39,4 +41,3 @@ export class Cat {
3941
public constructor() {
4042
}
4143
}
42-

samples/openapi3/client/petstore/typescript/builds/composed-schemas/models/Dog.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export class Dog {
1818

1919
static readonly discriminator: string | undefined = undefined;
2020

21+
static readonly mapping: {[index: string]: string} | undefined = undefined;
22+
2123
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
2224
{
2325
"name": "bark",
@@ -40,7 +42,6 @@ export class Dog {
4042
}
4143
}
4244

43-
4445
export enum DogBreedEnum {
4546
Dingo = 'Dingo',
4647
Husky = 'Husky',

0 commit comments

Comments
 (0)