diff --git a/bin/configs/typescript-fetch-any-of-union.yaml b/bin/configs/typescript-fetch-any-of-union.yaml
new file mode 100644
index 000000000000..829ea38dbe82
--- /dev/null
+++ b/bin/configs/typescript-fetch-any-of-union.yaml
@@ -0,0 +1,9 @@
+generatorName: typescript-fetch
+outputDir: samples/client/petstore/typescript-fetch/builds/any-of-union
+inputSpec: modules/openapi-generator/src/test/resources/3_0/typescript-fetch/anyOf.yaml
+templateDir: modules/openapi-generator/src/main/resources/typescript-fetch
+additionalProperties:
+ generateAnyOfAsUnion: true
+ npmVersion: 1.0.0
+ npmName: '@openapitools/typescript-fetch-petstore'
+ npmRepository: https://skimdb.npmjs.com/registry
diff --git a/docs/generators/typescript-fetch.md b/docs/generators/typescript-fetch.md
index 543e13061808..2dfc95b2f26d 100644
--- a/docs/generators/typescript-fetch.md
+++ b/docs/generators/typescript-fetch.md
@@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|enumPropertyNamingReplaceSpecialChar|Set to true to replace '-' and '+' symbols with 'minus_' and 'plus_' in enum of type string| |false|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response. With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
- **false**
- No changes to the enums are made, this is the default option.
- **true**
- With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false|
|fileNaming|Naming convention for the output files: 'PascalCase', 'camelCase', 'kebab-case'.| |PascalCase|
+|generateAnyOfAsUnion|Generate anyOf schemas as TypeScript union types instead of one interface merging all members' properties. A value matching several object members keeps the properties of all of them. An anyOf schema that also declares its own properties stays an interface.| |false|
|importFileExtension|File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html).| ||
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|- **true**
- The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.
- **false**
- The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.
|true|
|licenseName|The name of the license| |null|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
index 91991d569d74..bf6cc375765a 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
@@ -73,6 +73,8 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
public static final String DATE_LIBRARY_DATE = "date";
public static final String DATE_LIBRARY_STRING = "string";
public static final String DATE_LIBRARY_TEMPORAL = "temporal";
+ public static final String GENERATE_ANY_OF_AS_UNION = "generateAnyOfAsUnion";
+ public static final String GENERATE_ANY_OF_AS_UNION_DESC = "Generate anyOf schemas as TypeScript union types instead of one interface merging all members' properties. A value matching several object members keeps the properties of all of them. An anyOf schema that also declares its own properties stays an interface.";
public static final String STRING_ENUMS = "stringEnums";
public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values.";
public static final String IMPORT_FILE_EXTENSION_SWITCH = "importFileExtension";
@@ -96,6 +98,7 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
protected boolean addedModelIndex = false;
protected boolean withoutRuntimeChecks = false;
protected String dateLibrary = DATE_LIBRARY_DATE;
+ protected boolean generateAnyOfAsUnion = false;
protected boolean stringEnums = false;
protected String fileNaming = PASCAL_CASE;
protected String apiDocPath = "docs";
@@ -171,6 +174,7 @@ public TypeScriptFetchClientCodegen() {
dateLibraryOption.setEnum(dateOptions);
this.cliOptions.add(dateLibraryOption);
this.cliOptions.add(new CliOption(SAGAS_AND_RECORDS, "Setting this property to true will generate additional files for use with redux-saga and immutablejs.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
+ this.cliOptions.add(new CliOption(GENERATE_ANY_OF_AS_UNION, GENERATE_ANY_OF_AS_UNION_DESC, SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(STRING_ENUMS, STRING_ENUMS_DESC, SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(IMPORT_FILE_EXTENSION_SWITCH, IMPORT_FILE_EXTENSION_SWITCH_DESC).defaultValue(""));
this.cliOptions.add(new CliOption(FILE_NAMING, "Naming convention for the output files: 'PascalCase', 'camelCase', 'kebab-case'.").defaultValue(this.fileNaming));
@@ -236,6 +240,14 @@ public void setDateLibrary(String dateLibrary) {
this.dateLibrary = dateLibrary;
}
+ public Boolean getGenerateAnyOfAsUnion() {
+ return this.generateAnyOfAsUnion;
+ }
+
+ public void setGenerateAnyOfAsUnion(Boolean generateAnyOfAsUnion) {
+ this.generateAnyOfAsUnion = generateAnyOfAsUnion;
+ }
+
public Boolean getStringEnums() {
return this.stringEnums;
}
@@ -344,6 +356,10 @@ public void processOpts() {
this.setWithoutRuntimeChecks(convertPropertyToBoolean(WITHOUT_RUNTIME_CHECKS));
}
+ if (additionalProperties.containsKey(GENERATE_ANY_OF_AS_UNION)) {
+ this.setGenerateAnyOfAsUnion(convertPropertyToBoolean(GENERATE_ANY_OF_AS_UNION));
+ }
+
if (additionalProperties.containsKey(STRING_ENUMS)) {
this.setStringEnums(convertPropertyToBoolean(STRING_ENUMS));
additionalProperties.put("stringEnums", this.stringEnums);
@@ -604,6 +620,22 @@ public Map postProcessAllModels(Map objs)
}
}
+ // Split the oneOf/anyOf model members: the instanceOf check of an enum takes the primitive value itself,
+ // while the one of an object model needs an object.
+ Set enumModelNames = allModels.stream()
+ .filter(m -> m.isEnum)
+ .map(m -> m.classname)
+ .collect(Collectors.toSet());
+ for (ExtendedCodegenModel m : allModels) {
+ for (String member : m.oneOfModels) {
+ if (enumModelNames.contains(member)) {
+ m.oneOfEnumModels.add(member);
+ } else {
+ m.oneOfObjectModels.add(member);
+ }
+ }
+ }
+
for (ExtendedCodegenModel rootModel : allModels) {
for (String curImport : rootModel.imports) {
boolean isModelImport = false;
@@ -834,7 +866,11 @@ public ExtendedCodegenProperty fromProperty(String name, Schema p, boolean requi
@Override
public ExtendedCodegenModel fromModel(String name, Schema model) {
CodegenModel cm = super.fromModel(name, model);
- return new ExtendedCodegenModel(cm);
+ ExtendedCodegenModel result = new ExtendedCodegenModel(cm);
+ // The union template renders no properties, so an anyOf declaring its own properties stays an interface.
+ result.anyOfHasOwnProperties = model.getAnyOf() != null && !model.getAnyOf().isEmpty()
+ && model.getProperties() != null && !model.getProperties().isEmpty();
+ return result;
}
@Override
@@ -1081,8 +1117,20 @@ private ExtendedCodegenModel processCodeGenModel(ExtendedCodegenModel cm) {
.map(CodegenComposedSchemas::getOneOf)
.orElse(Collections.emptyList());
- // Type names omit branch nullability. Null is valid only when exactly one branch accepts it.
- if (oneOfsList.stream().filter(cp -> cp.isNullable).count() == 1) {
+ // With generateAnyOfAsUnion an anyOf is modeled like a oneOf, so the oneOf templates render it as a union.
+ boolean fromAnyOf = this.generateAnyOfAsUnion && cm.oneOf.isEmpty() && !cm.anyOf.isEmpty() && !cm.anyOfHasOwnProperties;
+ if (fromAnyOf) {
+ oneOfsList = Optional.ofNullable(cm.getComposedSchemas())
+ .map(CodegenComposedSchemas::getAnyOf)
+ .orElse(Collections.emptyList());
+ cm.oneOf.addAll(cm.anyOf);
+ cm.isAnyOfUnion = true;
+ }
+
+ // Type names omit branch nullability. For oneOf, null is valid only when exactly one branch accepts it;
+ // for anyOf, when at least one branch does.
+ long nullableBranches = oneOfsList.stream().filter(cp -> cp.isNullable).count();
+ if (fromAnyOf ? nullableBranches >= 1 : nullableBranches == 1) {
cm.oneOf.add("null");
}
@@ -2107,6 +2155,9 @@ public class ExtendedCodegenModel extends CodegenModel {
// 'TypedJSON' conversion methods in the composed model classes.
@Getter @Setter
public Set oneOfModels = new TreeSet<>();
+ // oneOfModels split by kind, see postProcessAllModels
+ public Set oneOfObjectModels = new TreeSet<>();
+ public Set oneOfEnumModels = new TreeSet<>();
@Getter @Setter
public Set oneOfArrays = new TreeSet<>();
@Getter @Setter
@@ -2115,6 +2166,9 @@ public class ExtendedCodegenModel extends CodegenModel {
public CodegenDiscriminator.MappedModel selfReferencingDiscriminatorMapping;
@Getter @Setter
public boolean parentIsOneOf; // true when this model's parent is a oneOf union type
+ @Getter @Setter
+ public boolean isAnyOfUnion; // true when an anyOf is generated as a union type (generateAnyOfAsUnion)
+ public boolean anyOfHasOwnProperties; // true when an anyOf schema declares properties next to its members
public boolean isEntity; // Is a model containing an "id" property marked as isUniqueId
public String returnPassthrough;
diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
index 62f9f104f7bf..717284d6d040 100644
--- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
@@ -44,20 +44,44 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
}
{{/discriminator}}
{{^discriminator}}
- {{#oneOfModels}}
+ {{#oneOfObjectModels}}
{{#-first}}
- if (typeof json !== 'object') {
- return json;
- }
+ if (typeof json === 'object') {
+ {{#isAnyOfUnion}}
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ {{/isAnyOfUnion}}
{{/-first}}
+ {{#isAnyOfUnion}}
+ if (instanceOf{{{.}}}(json)) {
+ anyOfResult = { ...anyOfResult, ...{{{.}}}FromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ {{/isAnyOfUnion}}
+ {{^isAnyOfUnion}}
+ if (instanceOf{{{.}}}(json)) {
+ return {{{.}}}FromJSONTyped(json, true);
+ }
+ {{/isAnyOfUnion}}
+ {{#-last}}
+ {{#isAnyOfUnion}}
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ {{/isAnyOfUnion}}
+ }
+ {{/-last}}
+ {{/oneOfObjectModels}}
+ {{#oneOfEnumModels}}
if (instanceOf{{{.}}}(json)) {
return {{{.}}}FromJSONTyped(json, true);
}
- {{/oneOfModels}}
+ {{/oneOfEnumModels}}
{{#oneOfArrays}}
{{#-first}}
if (Array.isArray(json)) {
- if (json.every(item => typeof item === 'object')) {
+ if (json.every(item => item !== null && typeof item === 'object')) {
{{/-first}}
if (json.every(item => instanceOf{{{.}}}(item))) {
return json.map(value => {{{.}}}FromJSONTyped(value, true));
@@ -197,20 +221,44 @@ export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDis
}
{{/discriminator}}
{{^discriminator}}
- {{#oneOfModels}}
+ {{#oneOfObjectModels}}
{{#-first}}
- if (typeof value !== 'object') {
- return value;
- }
+ if (typeof value === 'object') {
+ {{#isAnyOfUnion}}
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ {{/isAnyOfUnion}}
{{/-first}}
+ {{#isAnyOfUnion}}
+ if (instanceOf{{{.}}}(value)) {
+ anyOfResult = { ...anyOfResult, ...{{{.}}}ToJSON(value as {{{.}}}) };
+ anyOfMatched = true;
+ }
+ {{/isAnyOfUnion}}
+ {{^isAnyOfUnion}}
+ if (instanceOf{{{.}}}(value)) {
+ return {{{.}}}ToJSON(value as {{{.}}});
+ }
+ {{/isAnyOfUnion}}
+ {{#-last}}
+ {{#isAnyOfUnion}}
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ {{/isAnyOfUnion}}
+ }
+ {{/-last}}
+ {{/oneOfObjectModels}}
+ {{#oneOfEnumModels}}
if (instanceOf{{{.}}}(value)) {
return {{{.}}}ToJSON(value as {{{.}}});
}
- {{/oneOfModels}}
+ {{/oneOfEnumModels}}
{{#oneOfArrays}}
{{#-first}}
if (Array.isArray(value)) {
- if (value.every(item => typeof item === 'object')) {
+ if (value.every(item => item !== null && typeof item === 'object')) {
{{/-first}}
if (value.every(item => instanceOf{{{.}}}(item))) {
return value.map(value => {{{.}}}ToJSON(value as {{{.}}}));
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptFetchClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptFetchClientOptionsProvider.java
index 9b35b5074d35..efbeac0c2b23 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptFetchClientOptionsProvider.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptFetchClientOptionsProvider.java
@@ -30,6 +30,7 @@ public class TypeScriptFetchClientOptionsProvider implements TypeScriptSharedCli
private static final String NPM_REPOSITORY = "https://registry.npmjs.org";
public static final String SAGAS_AND_RECORDS = "false";
public static final String STRING_ENUMS = "false";
+ public static final String GENERATE_ANY_OF_AS_UNION = "false";
public static final String FILE_NAMING_VALUE = PASCAL_CASE;
public static final String DATE_LIBRARY_VALUE = TypeScriptFetchClientCodegen.DATE_LIBRARY_STRING;
@@ -53,6 +54,7 @@ public Map createOptions() {
.put(TypeScriptFetchClientCodegen.FILE_NAMING, FILE_NAMING_VALUE)
.put(TypeScriptFetchClientCodegen.DATE_LIBRARY, DATE_LIBRARY_VALUE)
.put(TypeScriptFetchClientCodegen.STRING_ENUMS, STRING_ENUMS)
+ .put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, GENERATE_ANY_OF_AS_UNION)
.put(TypeScriptFetchClientCodegen.USE_SQUARE_BRACKETS_IN_ARRAY_NAMES, Boolean.FALSE.toString())
.put(TypeScriptFetchClientCodegen.VALIDATION_ATTRIBUTES, Boolean.FALSE.toString())
.put(TypeScriptFetchClientCodegen.WITH_REQUEST_OPTS_IN_INTERFACE, Boolean.TRUE.toString())
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
index b9ad0d49bf0c..b980b9110f22 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
@@ -28,6 +28,7 @@
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
+import java.util.function.Function;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@@ -799,7 +800,7 @@ public void givenSchemaIsOneOfAndComposedSchemasArePrimitiveThenReturnStatements
Path exampleModelPath = Paths.get(outputPath + "/models/MyCustomSpeed.ts");
//FromJSON
- TestUtils.assertFileContains(exampleModelPath, "(typeof json !== 'object')");
+ TestUtils.assertFileContains(exampleModelPath, "(typeof json === 'object')");
TestUtils.assertFileContains(exampleModelPath, "(instanceOfMyNumericValue(json))");
TestUtils.assertFileContains(exampleModelPath, "(typeof json === 'number' && (json === 10 || json === 20 || json === 30))");
TestUtils.assertFileContains(exampleModelPath, "(typeof json === 'string' && (json === 'fixed-value-a' || json === 'fixed-value-b' || json === 'fixed-value-c'))");
@@ -807,7 +808,7 @@ public void givenSchemaIsOneOfAndComposedSchemasArePrimitiveThenReturnStatements
TestUtils.assertFileContains(exampleModelPath, "(json.every(item => typeof item === 'number'))");
TestUtils.assertFileContains(exampleModelPath, "(json.every(item => typeof item === 'string' && (item === 'oneof-array-enum-a' || item === 'oneof-array-enum-b' || item === 'oneof-array-enum-c')))");
//ToJSON
- TestUtils.assertFileContains(exampleModelPath, "(typeof value !== 'object')");
+ TestUtils.assertFileContains(exampleModelPath, "(typeof value === 'object')");
TestUtils.assertFileContains(exampleModelPath, "(instanceOfMyNumericValue(value))");
TestUtils.assertFileContains(exampleModelPath, "(typeof value === 'number' && (value === 10 || value === 20 || value === 30))");
TestUtils.assertFileContains(exampleModelPath, "(typeof value === 'string' && (value === 'fixed-value-a' || value === 'fixed-value-b' || value === 'fixed-value-c'))");
@@ -1417,6 +1418,154 @@ public void testExplodedObjectQueryParameter() throws IOException {
TestUtils.assertFileNotContains(api, "Object.keys(requestParameters['flatFilter'])");
}
+ private static final String ANY_OF_SPEC = "src/test/resources/3_0/typescript-fetch/anyOf.yaml";
+
+ @Test(description = "Verify anyOf stays one interface merging all members' properties by default")
+ public void testAnyOfIsMergedInterfaceByDefault() throws IOException {
+ File output = generate(new HashMap<>(), ANY_OF_SPEC);
+
+ Path petData = Paths.get(output + "/models/PetData.ts");
+ TestUtils.assertFileContains(petData, "export interface PetData {");
+ TestUtils.assertFileContains(petData, "meowCount: number;");
+ TestUtils.assertFileContains(petData, "barkCount: number;");
+ TestUtils.assertFileNotContains(petData, "export type PetData =");
+ }
+
+ @DataProvider
+ public Object[][] anyOfUnionRuntimeCheckModes() {
+ return new Object[][] {{false}, {true}};
+ }
+
+ @Test(dataProvider = "anyOfUnionRuntimeCheckModes", description = "Verify generateAnyOfAsUnion generates anyOf schemas as union types")
+ public void testGenerateAnyOfAsUnion(boolean withoutRuntimeChecks) throws IOException {
+ Map properties = new HashMap<>();
+ properties.put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, true);
+ properties.put(TypeScriptFetchClientCodegen.WITHOUT_RUNTIME_CHECKS, withoutRuntimeChecks);
+ File output = generate(properties, ANY_OF_SPEC);
+
+ // without runtime checks all types are declared in models/index.ts
+ Function modelFile = name ->
+ withoutRuntimeChecks ? Paths.get(output + "/models/index.ts") : Paths.get(output + "/models/" + name + ".ts");
+
+ // top-level anyOf of refs, and the anyOf hoisted from an inline property
+ TestUtils.assertFileContains(modelFile.apply("PetData"), "export type PetData = Cat | Dog;");
+ TestUtils.assertFileContains(modelFile.apply("CreatePetData"), "export type CreatePetData = Cat | Dog;");
+ // inline anyOf of primitives on a property (#19155)
+ TestUtils.assertFileContains(modelFile.apply("CreatePetContent"), "export type CreatePetContent = number | string;");
+ // model, array and primitive members
+ TestUtils.assertFileContains(modelFile.apply("MixedPet"), "export type MixedPet = Array | Cat | string;");
+ // null is valid when at least one branch is nullable (for oneOf: exactly one)
+ TestUtils.assertFileContains(modelFile.apply("NullableValue"), "export type NullableValue = null | number | string;");
+ TestUtils.assertFileContains(modelFile.apply("MultipleNullableValue"), "export type MultipleNullableValue = null | number | string;");
+
+ if (!withoutRuntimeChecks) {
+ Path petData = Paths.get(output + "/models/PetData.ts");
+ TestUtils.assertFileNotContains(petData, "export interface PetData");
+ TestUtils.assertFileContains(petData, "import type { Cat } from './Cat';");
+ TestUtils.assertFileContains(petData, "if (instanceOfCat(json)) {");
+ // a value matching several members keeps the fields of all of them
+ TestUtils.assertFileContains(petData, "anyOfResult = { ...anyOfResult, ...CatFromJSONTyped(json, true) };");
+ TestUtils.assertFileContains(petData, "anyOfResult = { ...anyOfResult, ...DogFromJSONTyped(json, true) };");
+ TestUtils.assertFileContains(petData, "anyOfResult = { ...anyOfResult, ...CatToJSON(value as Cat) };");
+ TestUtils.assertFileContains(petData, "anyOfResult = { ...anyOfResult, ...DogToJSON(value as Dog) };");
+ TestUtils.assertFileNotContains(petData, "return CatToJSON(value as Cat);");
+ TestUtils.assertFileContains(Paths.get(output + "/models/CreatePetContent.ts"), "if (typeof json === 'number') {");
+ }
+ }
+
+ @DataProvider
+ public Object[][] anyOfAsUnionOptionValues() {
+ return new Object[][] {{false}, {true}};
+ }
+
+ @Test(dataProvider = "anyOfAsUnionOptionValues", description = "Verify oneOf still returns the first matching member, also when generateAnyOfAsUnion is on")
+ public void testOneOfKeepsFirstMatchWithAnyOfUnionOption(boolean anyOfAsUnion) throws IOException {
+ Map properties = new HashMap<>();
+ properties.put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, anyOfAsUnion);
+ File output = generate(properties, "src/test/resources/3_0/typescript-fetch/oneOf.yaml");
+
+ Path testResponse = Paths.get(output + "/models/TestResponse.ts");
+ TestUtils.assertFileContains(testResponse, "return TestAFromJSONTyped(json, true);");
+ TestUtils.assertFileNotContains(testResponse, "anyOfResult");
+
+ // the model checks only run for objects, so the declared primitive check is reachable
+ TestUtils.assertFileContains(testResponse, "if (typeof json === 'object') {");
+ TestUtils.assertFileContains(testResponse, "if (typeof json === 'string') {");
+ TestUtils.assertFileContains(testResponse, "if (typeof value === 'object') {");
+ TestUtils.assertFileContains(testResponse, "if (typeof value === 'string') {");
+
+ // null items must not reach the instanceOf checks of array members
+ Path testArrayResponse = Paths.get(output + "/models/TestArrayResponse.ts");
+ TestUtils.assertFileContains(testArrayResponse, "json.every(item => item !== null && typeof item === 'object')");
+ TestUtils.assertFileContains(testArrayResponse, "value.every(item => item !== null && typeof item === 'object')");
+ TestUtils.assertFileNotContains(testArrayResponse, "every(item => typeof item === 'object')");
+ }
+
+ @Test(dataProvider = "anyOfUnionRuntimeCheckModes", description = "Verify an anyOf declaring its own properties stays an interface with generateAnyOfAsUnion")
+ public void testAnyOfWithOwnPropertiesStaysInterface(boolean withoutRuntimeChecks) throws IOException {
+ Map properties = new HashMap<>();
+ properties.put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, true);
+ properties.put(TypeScriptFetchClientCodegen.WITHOUT_RUNTIME_CHECKS, withoutRuntimeChecks);
+ File output = generate(properties, ANY_OF_SPEC);
+
+ Path model = withoutRuntimeChecks ? Paths.get(output + "/models/index.ts") : Paths.get(output + "/models/AnyOfWithProperties.ts");
+ TestUtils.assertFileContains(model, "export interface AnyOfWithProperties {");
+ TestUtils.assertFileContains(model, "label: string;");
+ TestUtils.assertFileNotContains(model, "export type AnyOfWithProperties =");
+ }
+
+ @Test(description = "Verify a oneOf of a model and a date-time reaches the date parsing, and an enum member is checked by value")
+ public void testOneOfModelWithDateTimeAndEnumMembers() throws IOException {
+ File output = generate(new HashMap<>(), ANY_OF_SPEC);
+
+ String dateTime = Files.readString(Paths.get(output + "/models/OneOfModelAndDateTime.ts"), StandardCharsets.UTF_8);
+ // the parse and serialize branches come after the object block, and no primitive is passed through before them
+ assertThat(dateTime.indexOf("if (typeof json === 'object') {")).isGreaterThan(-1)
+ .isLessThan(dateTime.indexOf("parseDateTime(json)"));
+ assertThat(dateTime.indexOf("if (typeof value === 'object') {")).isGreaterThan(-1)
+ .isLessThan(dateTime.indexOf("value instanceof Date"));
+ assertThat(dateTime).doesNotContain("typeof json !== 'object'").doesNotContain("typeof value !== 'object'");
+
+ // the instanceOf check of an enum takes the primitive value, so it must not be inside the object block
+ String enumUnion = Files.readString(Paths.get(output + "/models/OneOfModelAndEnum.ts"), StandardCharsets.UTF_8);
+ assertThat(enumUnion).contains("if (instanceOfColor(json)) {").contains("if (instanceOfColor(value)) {");
+ assertThat(enumUnion.indexOf("if (instanceOfColor(json)) {")).isGreaterThan(enumUnion.indexOf("if (instanceOfCat(json)) {"));
+ assertThat(enumUnion).doesNotContain("typeof json !== 'object'").doesNotContain("typeof value !== 'object'");
+ }
+
+ @Test(description = "Verify an anyOf with a discriminator keeps the discriminator switch and does not merge members")
+ public void testGenerateAnyOfAsUnionWithDiscriminator() throws IOException {
+ Map properties = new HashMap<>();
+ properties.put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, true);
+ File output = generate(properties, ANY_OF_SPEC);
+
+ Path model = Paths.get(output + "/models/DiscriminatedPet.ts");
+ TestUtils.assertFileContains(model, "export type DiscriminatedPet = { kind: 'cat' } & Cat | { kind: 'dog' } & Dog;");
+ TestUtils.assertFileContains(model, "switch (json['kind']) {");
+ TestUtils.assertFileNotContains(model, "anyOfResult");
+ }
+
+ @Test(description = "Verify an anyOf mixing a model, an array and a primitive merges only the object member")
+ public void testGenerateAnyOfAsUnionWithMixedMembers() throws IOException {
+ Map properties = new HashMap<>();
+ properties.put(TypeScriptFetchClientCodegen.GENERATE_ANY_OF_AS_UNION, true);
+ File output = generate(properties, ANY_OF_SPEC);
+
+ Path model = Paths.get(output + "/models/MixedPet.ts");
+ TestUtils.assertFileContains(model, "export type MixedPet = Array | Cat | string;");
+ TestUtils.assertFileContains(model, "anyOfResult = { ...anyOfResult, ...CatFromJSONTyped(json, true) };");
+ TestUtils.assertFileContains(model, "return json.map(value => DogFromJSONTyped(value, true));");
+ TestUtils.assertFileContains(model, "if (typeof json === 'string') {");
+ TestUtils.assertFileContains(model, "return value.map(value => DogToJSON(value as Dog));");
+ TestUtils.assertFileContains(model, "if (typeof value === 'string') {");
+ // the model checks only run for objects, so the primitive checks are reachable
+ TestUtils.assertFileContains(model, "if (typeof json === 'object') {");
+ TestUtils.assertFileContains(model, "if (typeof value === 'object') {");
+ // null items must not reach instanceOfDog
+ TestUtils.assertFileContains(model, "json.every(item => item !== null && typeof item === 'object')");
+ TestUtils.assertFileContains(model, "value.every(item => item !== null && typeof item === 'object')");
+ }
+
private static final String DATE_HANDLING_SPEC = "src/test/resources/3_0/typescript-fetch/date-handling.yaml";
private static File generate(
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientOptionsTest.java
index 711e09fcf993..2673f6871b7a 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientOptionsTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientOptionsTest.java
@@ -54,6 +54,7 @@ protected void verifyOptions() {
verify(clientCodegen).setSagasAndRecords(Boolean.valueOf(TypeScriptFetchClientOptionsProvider.SAGAS_AND_RECORDS));
verify(clientCodegen).setEnumUnknownDefaultCase(Boolean.parseBoolean(TypeScriptFetchClientOptionsProvider.ENUM_UNKNOWN_DEFAULT_CASE_VALUE));
verify(clientCodegen).setStringEnums(Boolean.parseBoolean(TypeScriptFetchClientOptionsProvider.STRING_ENUMS));
+ verify(clientCodegen).setGenerateAnyOfAsUnion(Boolean.parseBoolean(TypeScriptFetchClientOptionsProvider.GENERATE_ANY_OF_AS_UNION));
verify(clientCodegen).setFileNaming(TypeScriptFetchClientOptionsProvider.FILE_NAMING_VALUE);
verify(clientCodegen).setDateLibrary(TypeScriptFetchClientOptionsProvider.DATE_LIBRARY_VALUE);
}
diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/anyOf.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/anyOf.yaml
new file mode 100644
index 000000000000..25c9075cc0eb
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/anyOf.yaml
@@ -0,0 +1,116 @@
+openapi: 3.0.3
+info:
+ title: anyOf as union
+ version: 1.0.0
+paths:
+ /pets:
+ post:
+ operationId: createPet
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreatePet'
+ responses:
+ '200':
+ description: ok
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PetData'
+components:
+ schemas:
+ Cat:
+ type: object
+ properties:
+ kind:
+ type: string
+ meowCount:
+ type: integer
+ required:
+ - kind
+ - meowCount
+ Dog:
+ type: object
+ properties:
+ kind:
+ type: string
+ barkCount:
+ type: integer
+ tailLength:
+ type: integer
+ breed:
+ type: string
+ required:
+ - kind
+ - barkCount
+ - tailLength
+ PetData:
+ anyOf:
+ - $ref: '#/components/schemas/Cat'
+ - $ref: '#/components/schemas/Dog'
+ DiscriminatedPet:
+ anyOf:
+ - $ref: '#/components/schemas/Cat'
+ - $ref: '#/components/schemas/Dog'
+ discriminator:
+ propertyName: kind
+ mapping:
+ cat: '#/components/schemas/Cat'
+ dog: '#/components/schemas/Dog'
+ MixedPet:
+ anyOf:
+ - $ref: '#/components/schemas/Cat'
+ - type: array
+ items:
+ $ref: '#/components/schemas/Dog'
+ - type: string
+ AnyOfWithProperties:
+ anyOf:
+ - $ref: '#/components/schemas/Cat'
+ - $ref: '#/components/schemas/Dog'
+ properties:
+ label:
+ type: string
+ required:
+ - label
+ Color:
+ type: string
+ enum:
+ - red
+ - blue
+ OneOfModelAndEnum:
+ oneOf:
+ - $ref: '#/components/schemas/Cat'
+ - $ref: '#/components/schemas/Color'
+ OneOfModelAndDateTime:
+ oneOf:
+ - $ref: '#/components/schemas/Cat'
+ - type: string
+ format: date-time
+ NullableValue:
+ anyOf:
+ - type: string
+ nullable: true
+ - type: number
+ MultipleNullableValue:
+ anyOf:
+ - type: string
+ nullable: true
+ - type: number
+ nullable: true
+ CreatePet:
+ type: object
+ properties:
+ id:
+ type: string
+ data:
+ anyOf:
+ - $ref: '#/components/schemas/Cat'
+ - $ref: '#/components/schemas/Dog'
+ content:
+ anyOf:
+ - type: number
+ - type: string
+ required:
+ - id
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/.gitignore b/samples/client/petstore/typescript-fetch/builds/any-of-union/.gitignore
new file mode 100644
index 000000000000..149b57654723
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/.gitignore
@@ -0,0 +1,4 @@
+wwwroot/*.js
+node_modules
+typings
+dist
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/.npmignore b/samples/client/petstore/typescript-fetch/builds/any-of-union/.npmignore
new file mode 100644
index 000000000000..42061c01a1c7
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/.npmignore
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator-ignore b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/FILES b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/FILES
new file mode 100644
index 000000000000..95988ae13db7
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/FILES
@@ -0,0 +1,40 @@
+.gitignore
+.npmignore
+README.md
+docs/AnyOfWithProperties.md
+docs/Cat.md
+docs/Color.md
+docs/CreatePet.md
+docs/CreatePetContent.md
+docs/CreatePetData.md
+docs/DefaultApi.md
+docs/DiscriminatedPet.md
+docs/Dog.md
+docs/MixedPet.md
+docs/MultipleNullableValue.md
+docs/NullableValue.md
+docs/OneOfModelAndDateTime.md
+docs/OneOfModelAndEnum.md
+docs/PetData.md
+package.json
+src/apis/DefaultApi.ts
+src/apis/index.ts
+src/index.ts
+src/models/AnyOfWithProperties.ts
+src/models/Cat.ts
+src/models/Color.ts
+src/models/CreatePet.ts
+src/models/CreatePetContent.ts
+src/models/CreatePetData.ts
+src/models/DiscriminatedPet.ts
+src/models/Dog.ts
+src/models/MixedPet.ts
+src/models/MultipleNullableValue.ts
+src/models/NullableValue.ts
+src/models/OneOfModelAndDateTime.ts
+src/models/OneOfModelAndEnum.ts
+src/models/PetData.ts
+src/models/index.ts
+src/runtime.ts
+tsconfig.esm.json
+tsconfig.json
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/VERSION b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/VERSION
new file mode 100644
index 000000000000..56fe0e8b297f
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.27.0-SNAPSHOT
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/README.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/README.md
new file mode 100644
index 000000000000..4527782fcd0f
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/README.md
@@ -0,0 +1,125 @@
+# @openapitools/typescript-fetch-petstore@1.0.0
+
+A TypeScript SDK client for the localhost API.
+
+## Usage
+
+First, install the SDK from npm.
+
+```bash
+npm install @openapitools/typescript-fetch-petstore --save
+```
+
+Next, try it out.
+
+
+```ts
+import {
+ Configuration,
+ DefaultApi,
+} from '@openapitools/typescript-fetch-petstore';
+import type { CreatePetRequest } from '@openapitools/typescript-fetch-petstore';
+
+async function example() {
+ console.log("🚀 Testing @openapitools/typescript-fetch-petstore SDK...");
+ const api = new DefaultApi();
+
+ const body = {
+ // CreatePet (optional)
+ createPet: ...,
+ } satisfies CreatePetRequest;
+
+ try {
+ const data = await api.createPet(body);
+ console.log(data);
+ } catch (error) {
+ console.error(error);
+ }
+}
+
+// Run the test
+example().catch(console.error);
+```
+
+
+## Documentation
+
+### API Endpoints
+
+All URIs are relative to *http://localhost*
+
+| Class | Method | HTTP request | Description
+| ----- | ------ | ------------ | -------------
+*DefaultApi* | [**createPet**](docs/DefaultApi.md#createpet) | **POST** /pets |
+
+
+### Models
+
+- [AnyOfWithProperties](docs/AnyOfWithProperties.md)
+- [Cat](docs/Cat.md)
+- [Color](docs/Color.md)
+- [CreatePet](docs/CreatePet.md)
+- [CreatePetContent](docs/CreatePetContent.md)
+- [CreatePetData](docs/CreatePetData.md)
+- [DiscriminatedPet](docs/DiscriminatedPet.md)
+- [Dog](docs/Dog.md)
+- [MixedPet](docs/MixedPet.md)
+- [MultipleNullableValue](docs/MultipleNullableValue.md)
+- [NullableValue](docs/NullableValue.md)
+- [OneOfModelAndDateTime](docs/OneOfModelAndDateTime.md)
+- [OneOfModelAndEnum](docs/OneOfModelAndEnum.md)
+- [PetData](docs/PetData.md)
+
+### Authorization
+
+Endpoints do not require authorization.
+
+
+## About
+
+This TypeScript SDK client supports the [Fetch API](https://fetch.spec.whatwg.org/)
+and is automatically generated by the
+[OpenAPI Generator](https://openapi-generator.tech) project:
+
+- API version: `1.0.0`
+- Package version: `1.0.0`
+- Generator version: `7.27.0-SNAPSHOT`
+- Build package: `org.openapitools.codegen.languages.TypeScriptFetchClientCodegen`
+
+The generated npm module supports the following:
+
+- Environments
+ * Node.js
+ * Webpack
+ * Browserify
+- Language levels
+ * ES5 - you must have a Promises/A+ library installed
+ * ES6
+- Module systems
+ * CommonJS
+ * ES6 module system
+
+
+## Development
+
+### Building
+
+To build the TypeScript source code, you need to have Node.js and npm installed.
+After cloning the repository, navigate to the project directory and run:
+
+```bash
+npm install
+npm run build
+```
+
+### Publishing
+
+Once you've built the package, you can publish it to npm:
+
+```bash
+npm publish
+```
+
+## License
+
+[]()
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/AnyOfWithProperties.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/AnyOfWithProperties.md
new file mode 100644
index 000000000000..dc61e06da87f
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/AnyOfWithProperties.md
@@ -0,0 +1,44 @@
+
+# AnyOfWithProperties
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`label` | string
+`kind` | string
+`meowCount` | number
+`barkCount` | number
+`tailLength` | number
+`breed` | string
+
+## Example
+
+```typescript
+import type { AnyOfWithProperties } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "label": null,
+ "kind": null,
+ "meowCount": null,
+ "barkCount": null,
+ "tailLength": null,
+ "breed": null,
+} satisfies AnyOfWithProperties
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as AnyOfWithProperties
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Cat.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Cat.md
new file mode 100644
index 000000000000..19b5e5d3a9e9
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Cat.md
@@ -0,0 +1,36 @@
+
+# Cat
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+
+## Example
+
+```typescript
+import type { Cat } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+} satisfies Cat
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as Cat
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Color.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Color.md
new file mode 100644
index 000000000000..71d5f7588136
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Color.md
@@ -0,0 +1,32 @@
+
+# Color
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+
+## Example
+
+```typescript
+import type { Color } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+} satisfies Color
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as Color
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePet.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePet.md
new file mode 100644
index 000000000000..f445bd68dac0
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePet.md
@@ -0,0 +1,38 @@
+
+# CreatePet
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`id` | string
+`data` | [CreatePetData](CreatePetData.md)
+`content` | [CreatePetContent](CreatePetContent.md)
+
+## Example
+
+```typescript
+import type { CreatePet } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "id": null,
+ "data": null,
+ "content": null,
+} satisfies CreatePet
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as CreatePet
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetContent.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetContent.md
new file mode 100644
index 000000000000..b2c0f1a324d1
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetContent.md
@@ -0,0 +1,32 @@
+
+# CreatePetContent
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+
+## Example
+
+```typescript
+import type { CreatePetContent } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+} satisfies CreatePetContent
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as CreatePetContent
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetData.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetData.md
new file mode 100644
index 000000000000..666be577c004
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/CreatePetData.md
@@ -0,0 +1,42 @@
+
+# CreatePetData
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+`barkCount` | number
+`tailLength` | number
+`breed` | string
+
+## Example
+
+```typescript
+import type { CreatePetData } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+ "barkCount": null,
+ "tailLength": null,
+ "breed": null,
+} satisfies CreatePetData
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as CreatePetData
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DefaultApi.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DefaultApi.md
new file mode 100644
index 000000000000..2f2dee0e2b25
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DefaultApi.md
@@ -0,0 +1,74 @@
+# DefaultApi
+
+All URIs are relative to *http://localhost*
+
+| Method | HTTP request | Description |
+|------------- | ------------- | -------------|
+| [**createPet**](DefaultApi.md#createpet) | **POST** /pets | |
+
+
+
+## createPet
+
+> PetData createPet(createPet)
+
+
+
+### Example
+
+```ts
+import {
+ Configuration,
+ DefaultApi,
+} from '@openapitools/typescript-fetch-petstore';
+import type { CreatePetRequest } from '@openapitools/typescript-fetch-petstore';
+
+async function example() {
+ console.log("🚀 Testing @openapitools/typescript-fetch-petstore SDK...");
+ const api = new DefaultApi();
+
+ const body = {
+ // CreatePet (optional)
+ createPet: ...,
+ } satisfies CreatePetRequest;
+
+ try {
+ const data = await api.createPet(body);
+ console.log(data);
+ } catch (error) {
+ console.error(error);
+ }
+}
+
+// Run the test
+example().catch(console.error);
+```
+
+### Parameters
+
+
+| Name | Type | Description | Notes |
+|------------- | ------------- | ------------- | -------------|
+| **createPet** | [CreatePet](CreatePet.md) | | [Optional] |
+
+### Return type
+
+[**PetData**](PetData.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+- **Content-Type**: `application/json`
+- **Accept**: `application/json`
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | ok | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DiscriminatedPet.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DiscriminatedPet.md
new file mode 100644
index 000000000000..29600d84c633
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/DiscriminatedPet.md
@@ -0,0 +1,42 @@
+
+# DiscriminatedPet
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+`barkCount` | number
+`tailLength` | number
+`breed` | string
+
+## Example
+
+```typescript
+import type { DiscriminatedPet } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+ "barkCount": null,
+ "tailLength": null,
+ "breed": null,
+} satisfies DiscriminatedPet
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as DiscriminatedPet
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Dog.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Dog.md
new file mode 100644
index 000000000000..d1dcc8c5d722
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/Dog.md
@@ -0,0 +1,40 @@
+
+# Dog
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`barkCount` | number
+`tailLength` | number
+`breed` | string
+
+## Example
+
+```typescript
+import type { Dog } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "barkCount": null,
+ "tailLength": null,
+ "breed": null,
+} satisfies Dog
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as Dog
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MixedPet.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MixedPet.md
new file mode 100644
index 000000000000..67668bf156f0
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MixedPet.md
@@ -0,0 +1,36 @@
+
+# MixedPet
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+
+## Example
+
+```typescript
+import type { MixedPet } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+} satisfies MixedPet
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as MixedPet
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MultipleNullableValue.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MultipleNullableValue.md
new file mode 100644
index 000000000000..b0e3f2d7606a
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/MultipleNullableValue.md
@@ -0,0 +1,32 @@
+
+# MultipleNullableValue
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+
+## Example
+
+```typescript
+import type { MultipleNullableValue } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+} satisfies MultipleNullableValue
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as MultipleNullableValue
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/NullableValue.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/NullableValue.md
new file mode 100644
index 000000000000..ac1d89db3720
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/NullableValue.md
@@ -0,0 +1,32 @@
+
+# NullableValue
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+
+## Example
+
+```typescript
+import type { NullableValue } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+} satisfies NullableValue
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as NullableValue
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndDateTime.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndDateTime.md
new file mode 100644
index 000000000000..c92daa21cc21
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndDateTime.md
@@ -0,0 +1,36 @@
+
+# OneOfModelAndDateTime
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+
+## Example
+
+```typescript
+import type { OneOfModelAndDateTime } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+} satisfies OneOfModelAndDateTime
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as OneOfModelAndDateTime
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndEnum.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndEnum.md
new file mode 100644
index 000000000000..49a9ac7d91e0
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/OneOfModelAndEnum.md
@@ -0,0 +1,36 @@
+
+# OneOfModelAndEnum
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+
+## Example
+
+```typescript
+import type { OneOfModelAndEnum } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+} satisfies OneOfModelAndEnum
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as OneOfModelAndEnum
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/PetData.md b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/PetData.md
new file mode 100644
index 000000000000..ddc194ad9d1a
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/docs/PetData.md
@@ -0,0 +1,42 @@
+
+# PetData
+
+
+## Properties
+
+Name | Type
+------------ | -------------
+`kind` | string
+`meowCount` | number
+`barkCount` | number
+`tailLength` | number
+`breed` | string
+
+## Example
+
+```typescript
+import type { PetData } from '@openapitools/typescript-fetch-petstore'
+
+// TODO: Update the object below with actual values
+const example = {
+ "kind": null,
+ "meowCount": null,
+ "barkCount": null,
+ "tailLength": null,
+ "breed": null,
+} satisfies PetData
+
+console.log(example)
+
+// Convert the instance to a JSON string
+const exampleJSON: string = JSON.stringify(example)
+console.log(exampleJSON)
+
+// Parse the JSON string back to an object
+const exampleParsed = JSON.parse(exampleJSON) as PetData
+console.log(exampleParsed)
+```
+
+[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
+
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/package.json b/samples/client/petstore/typescript-fetch/builds/any-of-union/package.json
new file mode 100644
index 000000000000..6d44ed32b0c2
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@openapitools/typescript-fetch-petstore",
+ "version": "1.0.0",
+ "description": "OpenAPI client for @openapitools/typescript-fetch-petstore",
+ "author": "OpenAPI-Generator",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git"
+ },
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "module": "./dist/esm/index.js",
+ "sideEffects": false,
+ "scripts": {
+ "build": "tsc && tsc -p tsconfig.esm.json",
+ "prepare": "npm run build"
+ },
+ "devDependencies": {
+ "typescript": "^4.0 || ^5.0"
+ },
+ "publishConfig": {
+ "registry": "https://skimdb.npmjs.com/registry"
+ }
+}
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/DefaultApi.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/DefaultApi.ts
new file mode 100644
index 000000000000..027faee59365
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/DefaultApi.ts
@@ -0,0 +1,77 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 * as runtime from '../runtime';
+import {
+ type CreatePet,
+ CreatePetFromJSON,
+ CreatePetToJSON,
+} from '../models/CreatePet';
+import {
+ type PetData,
+ PetDataFromJSON,
+ PetDataToJSON,
+} from '../models/PetData';
+
+export interface CreatePetRequest {
+ /**
+ *
+ */
+ createPet?: CreatePet;
+}
+
+/**
+ *
+ */
+export class DefaultApi extends runtime.BaseAPI {
+
+ /**
+ * Creates request options for createPet without sending the request
+ */
+ async createPetRequestOpts(requestParameters: CreatePetRequest): Promise {
+ const queryParameters: any = {};
+
+ const headerParameters: runtime.HTTPHeaders = {};
+
+ headerParameters['Content-Type'] = 'application/json';
+
+
+ let urlPath = `/pets`;
+
+ return {
+ path: urlPath,
+ method: 'POST',
+ headers: headerParameters,
+ query: queryParameters,
+ body: CreatePetToJSON(requestParameters['createPet']),
+ };
+ }
+
+ /**
+ */
+ async createPetRaw(requestParameters: CreatePetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> {
+ const requestOptions = await this.createPetRequestOpts(requestParameters);
+ const response = await this.request(requestOptions, initOverrides);
+
+ return new runtime.JSONApiResponse(response, (jsonValue) => PetDataFromJSON(jsonValue));
+ }
+
+ /**
+ */
+ async createPet(requestParameters: CreatePetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise {
+ const response = await this.createPetRaw(requestParameters, initOverrides);
+ return await response.value();
+ }
+
+}
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/index.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/index.ts
new file mode 100644
index 000000000000..69c44c00fa0d
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/apis/index.ts
@@ -0,0 +1,3 @@
+/* tslint:disable */
+/* eslint-disable */
+export * from './DefaultApi';
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/index.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/index.ts
new file mode 100644
index 000000000000..bebe8bbbe206
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/index.ts
@@ -0,0 +1,5 @@
+/* tslint:disable */
+/* eslint-disable */
+export * from './runtime';
+export * from './apis/index';
+export * from './models/index';
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/AnyOfWithProperties.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/AnyOfWithProperties.ts
new file mode 100644
index 000000000000..e4c5926f7947
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/AnyOfWithProperties.ts
@@ -0,0 +1,113 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { mapValues } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+ CatToJSONTyped,
+} from './Cat';
+import type { Dog } from './Dog';
+import {
+ DogFromJSON,
+ DogFromJSONTyped,
+ DogToJSON,
+ DogToJSONTyped,
+} from './Dog';
+
+/**
+ *
+ * @export
+ * @interface AnyOfWithProperties
+ */
+export interface AnyOfWithProperties {
+ /**
+ *
+ */
+ label: string;
+ /**
+ *
+ */
+ kind: string;
+ /**
+ *
+ */
+ meowCount: number;
+ /**
+ *
+ */
+ barkCount: number;
+ /**
+ *
+ */
+ tailLength: number;
+ /**
+ *
+ */
+ breed?: string;
+}
+
+/**
+ * Check if a given object implements the AnyOfWithProperties interface.
+ */
+export function instanceOfAnyOfWithProperties(value: object): value is AnyOfWithProperties {
+ if (!('label' in value) || value['label'] === undefined) return false;
+ if (!('kind' in value) || value['kind'] === undefined) return false;
+ if (!('meowCount' in value) || value['meowCount'] === undefined) return false;
+ if (!('barkCount' in value) || value['barkCount'] === undefined) return false;
+ if (!('tailLength' in value) || value['tailLength'] === undefined) return false;
+ return true;
+}
+
+export function AnyOfWithPropertiesFromJSON(json: any): AnyOfWithProperties {
+ return AnyOfWithPropertiesFromJSONTyped(json, false);
+}
+
+export function AnyOfWithPropertiesFromJSONTyped(json: any, ignoreDiscriminator: boolean): AnyOfWithProperties {
+ if (json == null) {
+ return json;
+ }
+ return {
+
+ 'label': json['label'],
+ 'kind': json['kind'],
+ 'meowCount': json['meowCount'],
+ 'barkCount': json['barkCount'],
+ 'tailLength': json['tailLength'],
+ 'breed': json['breed'] == null ? undefined : json['breed'],
+ };
+}
+
+export function AnyOfWithPropertiesToJSON(json: any): AnyOfWithProperties {
+ return AnyOfWithPropertiesToJSONTyped(json, false);
+}
+
+export function AnyOfWithPropertiesToJSONTyped(value?: AnyOfWithProperties | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+
+ return {
+
+ 'label': value['label'],
+ 'kind': value['kind'],
+ 'meowCount': value['meowCount'],
+ 'barkCount': value['barkCount'],
+ 'tailLength': value['tailLength'],
+ 'breed': value['breed'],
+ };
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Cat.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Cat.ts
new file mode 100644
index 000000000000..a96ed94c8868
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Cat.ts
@@ -0,0 +1,71 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { mapValues } from '../runtime';
+/**
+ *
+ * @export
+ * @interface Cat
+ */
+export interface Cat {
+ /**
+ *
+ */
+ kind: string;
+ /**
+ *
+ */
+ meowCount: number;
+}
+
+/**
+ * Check if a given object implements the Cat interface.
+ */
+export function instanceOfCat(value: object): value is Cat {
+ if (!('kind' in value) || value['kind'] === undefined) return false;
+ if (!('meowCount' in value) || value['meowCount'] === undefined) return false;
+ return true;
+}
+
+export function CatFromJSON(json: any): Cat {
+ return CatFromJSONTyped(json, false);
+}
+
+export function CatFromJSONTyped(json: any, ignoreDiscriminator: boolean): Cat {
+ if (json == null) {
+ return json;
+ }
+ return {
+
+ 'kind': json['kind'],
+ 'meowCount': json['meowCount'],
+ };
+}
+
+export function CatToJSON(json: any): Cat {
+ return CatToJSONTyped(json, false);
+}
+
+export function CatToJSONTyped(value?: Cat | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+
+ return {
+
+ 'kind': value['kind'],
+ 'meowCount': value['meowCount'],
+ };
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Color.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Color.ts
new file mode 100644
index 000000000000..ca0d71d5bd87
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Color.ts
@@ -0,0 +1,53 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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
+ */
+export const Color = {
+ Red: 'red',
+ Blue: 'blue',
+} as const;
+export type Color = typeof Color[keyof typeof Color];
+
+
+export function instanceOfColor(value: any): boolean {
+ for (const key in Color) {
+ if (Object.prototype.hasOwnProperty.call(Color, key)) {
+ if (Color[key as keyof typeof Color] === value) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+export function ColorFromJSON(json: any): Color {
+ return ColorFromJSONTyped(json, false);
+}
+
+export function ColorFromJSONTyped(json: any, ignoreDiscriminator: boolean): Color {
+ return json as Color;
+}
+
+export function ColorToJSON(value?: Color | null): any {
+ return value as any;
+}
+
+export function ColorToJSONTyped(value: any, ignoreDiscriminator: boolean): Color {
+ return value as Color;
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePet.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePet.ts
new file mode 100644
index 000000000000..87fd63f1c9bf
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePet.ts
@@ -0,0 +1,91 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { mapValues } from '../runtime';
+import type { CreatePetData } from './CreatePetData';
+import {
+ CreatePetDataFromJSON,
+ CreatePetDataFromJSONTyped,
+ CreatePetDataToJSON,
+ CreatePetDataToJSONTyped,
+} from './CreatePetData';
+import type { CreatePetContent } from './CreatePetContent';
+import {
+ CreatePetContentFromJSON,
+ CreatePetContentFromJSONTyped,
+ CreatePetContentToJSON,
+ CreatePetContentToJSONTyped,
+} from './CreatePetContent';
+
+/**
+ *
+ * @export
+ * @interface CreatePet
+ */
+export interface CreatePet {
+ /**
+ *
+ */
+ id: string;
+ /**
+ *
+ */
+ data?: CreatePetData;
+ /**
+ *
+ */
+ content?: CreatePetContent;
+}
+
+/**
+ * Check if a given object implements the CreatePet interface.
+ */
+export function instanceOfCreatePet(value: object): value is CreatePet {
+ if (!('id' in value) || value['id'] === undefined) return false;
+ return true;
+}
+
+export function CreatePetFromJSON(json: any): CreatePet {
+ return CreatePetFromJSONTyped(json, false);
+}
+
+export function CreatePetFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreatePet {
+ if (json == null) {
+ return json;
+ }
+ return {
+
+ 'id': json['id'],
+ 'data': json['data'] == null ? undefined : CreatePetDataFromJSON(json['data']),
+ 'content': json['content'] == null ? undefined : CreatePetContentFromJSON(json['content']),
+ };
+}
+
+export function CreatePetToJSON(json: any): CreatePet {
+ return CreatePetToJSONTyped(json, false);
+}
+
+export function CreatePetToJSONTyped(value?: CreatePet | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+
+ return {
+
+ 'id': value['id'],
+ 'data': CreatePetDataToJSON(value['data']),
+ 'content': CreatePetContentToJSON(value['content']),
+ };
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetContent.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetContent.ts
new file mode 100644
index 000000000000..1867afc78237
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetContent.ts
@@ -0,0 +1,56 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+/**
+ * @type CreatePetContent
+ *
+ * @export
+ */
+export type CreatePetContent = number | string;
+
+export function CreatePetContentFromJSON(json: any): CreatePetContent {
+ return CreatePetContentFromJSONTyped(json, false);
+}
+
+export function CreatePetContentFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreatePetContent {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'number') {
+ return json;
+ }
+ if (typeof json === 'string') {
+ return json;
+ }
+ return {} as any;
+}
+
+export function CreatePetContentToJSON(json: any): any {
+ return CreatePetContentToJSONTyped(json, false);
+}
+
+export function CreatePetContentToJSONTyped(value?: CreatePetContent | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'number') {
+ return value;
+ }
+ if (typeof value === 'string') {
+ return value;
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetData.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetData.ts
new file mode 100644
index 000000000000..f30d8e035555
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/CreatePetData.ts
@@ -0,0 +1,91 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+import type { Dog } from './Dog';
+import {
+ instanceOfDog,
+ DogFromJSON,
+ DogFromJSONTyped,
+ DogToJSON,
+} from './Dog';
+
+/**
+ * @type CreatePetData
+ *
+ * @export
+ */
+export type CreatePetData = Cat | Dog;
+
+export function CreatePetDataFromJSON(json: any): CreatePetData {
+ return CreatePetDataFromJSONTyped(json, false);
+}
+
+export function CreatePetDataFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreatePetData {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(json)) {
+ anyOfResult = { ...anyOfResult, ...CatFromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ if (instanceOfDog(json)) {
+ anyOfResult = { ...anyOfResult, ...DogFromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ return {} as any;
+}
+
+export function CreatePetDataToJSON(json: any): any {
+ return CreatePetDataToJSONTyped(json, false);
+}
+
+export function CreatePetDataToJSONTyped(value?: CreatePetData | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(value)) {
+ anyOfResult = { ...anyOfResult, ...CatToJSON(value as Cat) };
+ anyOfMatched = true;
+ }
+ if (instanceOfDog(value)) {
+ anyOfResult = { ...anyOfResult, ...DogToJSON(value as Dog) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/DiscriminatedPet.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/DiscriminatedPet.ts
new file mode 100644
index 000000000000..5d497dff19f7
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/DiscriminatedPet.ts
@@ -0,0 +1,73 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+import type { Dog } from './Dog';
+import {
+ instanceOfDog,
+ DogFromJSON,
+ DogFromJSONTyped,
+ DogToJSON,
+} from './Dog';
+
+/**
+ * @type DiscriminatedPet
+ *
+ * @export
+ */
+export type DiscriminatedPet = { kind: 'cat' } & Cat | { kind: 'dog' } & Dog;
+
+export function DiscriminatedPetFromJSON(json: any): DiscriminatedPet {
+ return DiscriminatedPetFromJSONTyped(json, false);
+}
+
+export function DiscriminatedPetFromJSONTyped(json: any, ignoreDiscriminator: boolean): DiscriminatedPet {
+ if (json == null) {
+ return json;
+ }
+ switch (json['kind']) {
+ case 'cat':
+ return Object.assign({}, CatFromJSONTyped(json, true), { kind: 'cat' } as const);
+ case 'dog':
+ return Object.assign({}, DogFromJSONTyped(json, true), { kind: 'dog' } as const);
+ default:
+ return json;
+ }
+}
+
+export function DiscriminatedPetToJSON(json: any): any {
+ return DiscriminatedPetToJSONTyped(json, false);
+}
+
+export function DiscriminatedPetToJSONTyped(value?: DiscriminatedPet | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ switch (value['kind']) {
+ case 'cat':
+ return Object.assign({}, CatToJSON(value), { 'kind': 'cat' } as const);
+ case 'dog':
+ return Object.assign({}, DogToJSON(value), { 'kind': 'dog' } as const);
+ default:
+ return value;
+ }
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Dog.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Dog.ts
new file mode 100644
index 000000000000..67abfb3cac9d
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/Dog.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { mapValues } from '../runtime';
+/**
+ *
+ * @export
+ * @interface Dog
+ */
+export interface Dog {
+ /**
+ *
+ */
+ kind: string;
+ /**
+ *
+ */
+ barkCount: number;
+ /**
+ *
+ */
+ tailLength: number;
+ /**
+ *
+ */
+ breed?: string;
+}
+
+/**
+ * Check if a given object implements the Dog interface.
+ */
+export function instanceOfDog(value: object): value is Dog {
+ if (!('kind' in value) || value['kind'] === undefined) return false;
+ if (!('barkCount' in value) || value['barkCount'] === undefined) return false;
+ if (!('tailLength' in value) || value['tailLength'] === undefined) return false;
+ return true;
+}
+
+export function DogFromJSON(json: any): Dog {
+ return DogFromJSONTyped(json, false);
+}
+
+export function DogFromJSONTyped(json: any, ignoreDiscriminator: boolean): Dog {
+ if (json == null) {
+ return json;
+ }
+ return {
+
+ 'kind': json['kind'],
+ 'barkCount': json['barkCount'],
+ 'tailLength': json['tailLength'],
+ 'breed': json['breed'] == null ? undefined : json['breed'],
+ };
+}
+
+export function DogToJSON(json: any): Dog {
+ return DogToJSONTyped(json, false);
+}
+
+export function DogToJSONTyped(value?: Dog | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+
+ return {
+
+ 'kind': value['kind'],
+ 'barkCount': value['barkCount'],
+ 'tailLength': value['tailLength'],
+ 'breed': value['breed'],
+ };
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MixedPet.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MixedPet.ts
new file mode 100644
index 000000000000..690999551d47
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MixedPet.ts
@@ -0,0 +1,109 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Dog } from './Dog';
+import {
+ instanceOfDog,
+ DogFromJSON,
+ DogFromJSONTyped,
+ DogToJSON,
+} from './Dog';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+
+/**
+ * @type MixedPet
+ *
+ * @export
+ */
+export type MixedPet = Array | Cat | string;
+
+export function MixedPetFromJSON(json: any): MixedPet {
+ return MixedPetFromJSONTyped(json, false);
+}
+
+export function MixedPetFromJSONTyped(json: any, ignoreDiscriminator: boolean): MixedPet {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(json)) {
+ anyOfResult = { ...anyOfResult, ...CatFromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ if (Array.isArray(json)) {
+ if (json.every(item => item !== null && typeof item === 'object')) {
+ if (json.every(item => instanceOfDog(item))) {
+ return json.map(value => DogFromJSONTyped(value, true));
+ }
+ }
+ }
+ if (Array.isArray(json)) {
+ return json;
+ }
+ if (typeof json === 'string') {
+ return json;
+ }
+ return {} as any;
+}
+
+export function MixedPetToJSON(json: any): any {
+ return MixedPetToJSONTyped(json, false);
+}
+
+export function MixedPetToJSONTyped(value?: MixedPet | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(value)) {
+ anyOfResult = { ...anyOfResult, ...CatToJSON(value as Cat) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ if (Array.isArray(value)) {
+ if (value.every(item => item !== null && typeof item === 'object')) {
+ if (value.every(item => instanceOfDog(item))) {
+ return value.map(value => DogToJSON(value as Dog));
+ }
+ }
+ }
+ if (Array.isArray(value)) {
+ return value;
+ }
+ if (typeof value === 'string') {
+ return value;
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MultipleNullableValue.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MultipleNullableValue.ts
new file mode 100644
index 000000000000..78ad42ff2abb
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/MultipleNullableValue.ts
@@ -0,0 +1,56 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+/**
+ * @type MultipleNullableValue
+ *
+ * @export
+ */
+export type MultipleNullableValue = null | number | string;
+
+export function MultipleNullableValueFromJSON(json: any): MultipleNullableValue {
+ return MultipleNullableValueFromJSONTyped(json, false);
+}
+
+export function MultipleNullableValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): MultipleNullableValue {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'number') {
+ return json;
+ }
+ if (typeof json === 'string') {
+ return json;
+ }
+ return {} as any;
+}
+
+export function MultipleNullableValueToJSON(json: any): any {
+ return MultipleNullableValueToJSONTyped(json, false);
+}
+
+export function MultipleNullableValueToJSONTyped(value?: MultipleNullableValue | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'number') {
+ return value;
+ }
+ if (typeof value === 'string') {
+ return value;
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/NullableValue.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/NullableValue.ts
new file mode 100644
index 000000000000..bd72c9f37696
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/NullableValue.ts
@@ -0,0 +1,56 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+/**
+ * @type NullableValue
+ *
+ * @export
+ */
+export type NullableValue = null | number | string;
+
+export function NullableValueFromJSON(json: any): NullableValue {
+ return NullableValueFromJSONTyped(json, false);
+}
+
+export function NullableValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): NullableValue {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'number') {
+ return json;
+ }
+ if (typeof json === 'string') {
+ return json;
+ }
+ return {} as any;
+}
+
+export function NullableValueToJSON(json: any): any {
+ return NullableValueToJSONTyped(json, false);
+}
+
+export function NullableValueToJSONTyped(value?: NullableValue | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'number') {
+ return value;
+ }
+ if (typeof value === 'string') {
+ return value;
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndDateTime.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndDateTime.ts
new file mode 100644
index 000000000000..96b23f0fdd53
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndDateTime.ts
@@ -0,0 +1,68 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+
+/**
+ * @type OneOfModelAndDateTime
+ *
+ * @export
+ */
+export type OneOfModelAndDateTime = Cat | Date;
+
+export function OneOfModelAndDateTimeFromJSON(json: any): OneOfModelAndDateTime {
+ return OneOfModelAndDateTimeFromJSONTyped(json, false);
+}
+
+export function OneOfModelAndDateTimeFromJSONTyped(json: any, ignoreDiscriminator: boolean): OneOfModelAndDateTime {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'object') {
+ if (instanceOfCat(json)) {
+ return CatFromJSONTyped(json, true);
+ }
+ }
+ if (!(isNaN(parseDateTime(json).getTime()))) {
+ return json == null ? undefined : (parseDateTime(json));
+ }
+ return {} as any;
+}
+
+export function OneOfModelAndDateTimeToJSON(json: any): any {
+ return OneOfModelAndDateTimeToJSONTyped(json, false);
+}
+
+export function OneOfModelAndDateTimeToJSONTyped(value?: OneOfModelAndDateTime | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'object') {
+ if (instanceOfCat(value)) {
+ return CatToJSON(value as Cat);
+ }
+ }
+ if (value instanceof Date) {
+ return value == null ? undefined : (serializeDateTime(value));
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndEnum.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndEnum.ts
new file mode 100644
index 000000000000..26f1d6f70711
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/OneOfModelAndEnum.ts
@@ -0,0 +1,75 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+import type { Color } from './Color';
+import {
+ instanceOfColor,
+ ColorFromJSON,
+ ColorFromJSONTyped,
+ ColorToJSON,
+} from './Color';
+
+/**
+ * @type OneOfModelAndEnum
+ *
+ * @export
+ */
+export type OneOfModelAndEnum = Cat | Color;
+
+export function OneOfModelAndEnumFromJSON(json: any): OneOfModelAndEnum {
+ return OneOfModelAndEnumFromJSONTyped(json, false);
+}
+
+export function OneOfModelAndEnumFromJSONTyped(json: any, ignoreDiscriminator: boolean): OneOfModelAndEnum {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'object') {
+ if (instanceOfCat(json)) {
+ return CatFromJSONTyped(json, true);
+ }
+ }
+ if (instanceOfColor(json)) {
+ return ColorFromJSONTyped(json, true);
+ }
+ return {} as any;
+}
+
+export function OneOfModelAndEnumToJSON(json: any): any {
+ return OneOfModelAndEnumToJSONTyped(json, false);
+}
+
+export function OneOfModelAndEnumToJSONTyped(value?: OneOfModelAndEnum | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'object') {
+ if (instanceOfCat(value)) {
+ return CatToJSON(value as Cat);
+ }
+ }
+ if (instanceOfColor(value)) {
+ return ColorToJSON(value as Color);
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/PetData.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/PetData.ts
new file mode 100644
index 000000000000..ca1c29b93aa6
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/PetData.ts
@@ -0,0 +1,91 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Cat } from './Cat';
+import {
+ instanceOfCat,
+ CatFromJSON,
+ CatFromJSONTyped,
+ CatToJSON,
+} from './Cat';
+import type { Dog } from './Dog';
+import {
+ instanceOfDog,
+ DogFromJSON,
+ DogFromJSONTyped,
+ DogToJSON,
+} from './Dog';
+
+/**
+ * @type PetData
+ *
+ * @export
+ */
+export type PetData = Cat | Dog;
+
+export function PetDataFromJSON(json: any): PetData {
+ return PetDataFromJSONTyped(json, false);
+}
+
+export function PetDataFromJSONTyped(json: any, ignoreDiscriminator: boolean): PetData {
+ if (json == null) {
+ return json;
+ }
+ if (typeof json === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(json)) {
+ anyOfResult = { ...anyOfResult, ...CatFromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ if (instanceOfDog(json)) {
+ anyOfResult = { ...anyOfResult, ...DogFromJSONTyped(json, true) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ return {} as any;
+}
+
+export function PetDataToJSON(json: any): any {
+ return PetDataToJSONTyped(json, false);
+}
+
+export function PetDataToJSONTyped(value?: PetData | null, ignoreDiscriminator: boolean = false): any {
+ if (value == null) {
+ return value;
+ }
+ if (typeof value === 'object') {
+ // anyOf: a value may match several members, so combine all of them instead of keeping the first match
+ let anyOfResult: any = {};
+ let anyOfMatched = false;
+ if (instanceOfCat(value)) {
+ anyOfResult = { ...anyOfResult, ...CatToJSON(value as Cat) };
+ anyOfMatched = true;
+ }
+ if (instanceOfDog(value)) {
+ anyOfResult = { ...anyOfResult, ...DogToJSON(value as Dog) };
+ anyOfMatched = true;
+ }
+ if (anyOfMatched) {
+ return anyOfResult;
+ }
+ }
+ return {};
+}
+
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/index.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/index.ts
new file mode 100644
index 000000000000..5e9b105ab02d
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/models/index.ts
@@ -0,0 +1,16 @@
+/* tslint:disable */
+/* eslint-disable */
+export * from './AnyOfWithProperties';
+export * from './Cat';
+export * from './Color';
+export * from './CreatePet';
+export * from './CreatePetContent';
+export * from './CreatePetData';
+export * from './DiscriminatedPet';
+export * from './Dog';
+export * from './MixedPet';
+export * from './MultipleNullableValue';
+export * from './NullableValue';
+export * from './OneOfModelAndDateTime';
+export * from './OneOfModelAndEnum';
+export * from './PetData';
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/src/runtime.ts b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/runtime.ts
new file mode 100644
index 000000000000..dfd140a7b89f
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/src/runtime.ts
@@ -0,0 +1,572 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * anyOf as union
+ * 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 const BASE_PATH: string = "http://localhost".replace(/\/+$/, "");
+
+export interface ConfigurationParameters {
+ basePath?: string; // override base path
+ fetchApi?: FetchAPI; // override for fetch implementation
+ middleware?: Middleware[]; // middleware to apply before/after fetch requests
+ queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings
+ username?: string; // parameter for basic security
+ password?: string; // parameter for basic security
+ apiKey?: string | Promise | ((name: string) => string | Promise); // parameter for apiKey security
+ accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security
+ headers?: HTTPHeaders; //header params we want to use on every request
+ credentials?: RequestCredentials; //value for the credentials param we want to use on each request
+}
+
+export class Configuration {
+ constructor(private configuration: ConfigurationParameters = {}) {}
+
+ set config(configuration: Configuration) {
+ this.configuration = configuration;
+ }
+
+ get basePath(): string {
+ return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
+ }
+
+ get fetchApi(): FetchAPI | undefined {
+ return this.configuration.fetchApi;
+ }
+
+ get middleware(): Middleware[] {
+ return this.configuration.middleware || [];
+ }
+
+ get queryParamsStringify(): (params: HTTPQuery) => string {
+ return this.configuration.queryParamsStringify || querystring;
+ }
+
+ get username(): string | undefined {
+ return this.configuration.username;
+ }
+
+ get password(): string | undefined {
+ return this.configuration.password;
+ }
+
+ get apiKey(): ((name: string) => string | Promise) | undefined {
+ const apiKey = this.configuration.apiKey;
+ if (apiKey) {
+ return typeof apiKey === 'function' ? apiKey : () => apiKey;
+ }
+ return undefined;
+ }
+
+ get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined {
+ const accessToken = this.configuration.accessToken;
+ if (accessToken) {
+ return typeof accessToken === 'function' ? accessToken : async () => accessToken;
+ }
+ return undefined;
+ }
+
+ get headers(): HTTPHeaders | undefined {
+ return this.configuration.headers;
+ }
+
+ get credentials(): RequestCredentials | undefined {
+ return this.configuration.credentials;
+ }
+}
+
+export const DefaultConfig: Configuration = new Configuration();
+
+/**
+ * This is the base class for all generated API classes.
+ */
+export class BaseAPI {
+
+ private static readonly jsonRegex = /^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$/i;
+ private middleware: Middleware[];
+
+ constructor(protected configuration: Configuration = DefaultConfig) {
+ this.middleware = configuration.middleware;
+ }
+
+ withMiddleware(this: T, ...middlewares: Middleware[]): T {
+ const next = this.clone();
+ next.middleware = next.middleware.concat(...middlewares);
+ return next;
+ }
+
+ withPreMiddleware(this: T, ...preMiddlewares: Array): T {
+ const middlewares = preMiddlewares.map((pre) => ({ pre }));
+ return this.withMiddleware(...middlewares);
+ }
+
+ withPostMiddleware(this: T, ...postMiddlewares: Array): T {
+ const middlewares = postMiddlewares.map((post) => ({ post }));
+ return this.withMiddleware(...middlewares);
+ }
+
+ /**
+ * Check if the given MIME is a JSON MIME.
+ * JSON MIME examples:
+ * application/json
+ * application/json; charset=UTF8
+ * APPLICATION/JSON
+ * application/vnd.company+json
+ * @param mime - MIME (Multipurpose Internet Mail Extensions)
+ * @return True if the given MIME is JSON, false otherwise.
+ */
+ protected isJsonMime(mime: string | null | undefined): boolean {
+ if (!mime) {
+ return false;
+ }
+ return BaseAPI.jsonRegex.test(mime);
+ }
+
+ protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise {
+ const { url, init } = await this.createFetchParams(context, initOverrides);
+ const response = await this.fetchApi(url, init);
+ if (response && (response.status >= 200 && response.status < 300)) {
+ return response;
+ }
+ throw new ResponseError(response, 'Response returned an error code');
+ }
+
+ private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) {
+ let url = this.configuration.basePath + context.path;
+ if (context.query !== undefined && Object.keys(context.query).length !== 0) {
+ // only add the querystring to the URL if there are query parameters.
+ // this is done to avoid urls ending with a "?" character which buggy webservers
+ // do not handle correctly sometimes.
+ url += '?' + this.configuration.queryParamsStringify(context.query);
+ }
+
+ const headers = Object.assign({}, this.configuration.headers, context.headers);
+ Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {});
+
+ const initOverrideFn =
+ typeof initOverrides === "function"
+ ? initOverrides
+ : async () => initOverrides;
+
+ const initParams = {
+ method: context.method,
+ headers,
+ body: context.body,
+ credentials: this.configuration.credentials,
+ };
+
+ const overriddenInit: RequestInit = {
+ ...initParams,
+ ...(await initOverrideFn({
+ init: initParams,
+ context,
+ }))
+ };
+
+ let body: any;
+ if (isFormData(overriddenInit.body)
+ || (overriddenInit.body instanceof URLSearchParams)
+ || isBlob(overriddenInit.body)) {
+ body = overriddenInit.body;
+ } else if (this.isJsonMime(headers['Content-Type'])) {
+ body = JSON.stringify(overriddenInit.body);
+ } else {
+ body = overriddenInit.body;
+ }
+
+ const init: RequestInit = {
+ ...overriddenInit,
+ body
+ };
+
+ return { url, init };
+ }
+
+ private fetchApi = async (url: string, init: RequestInit) => {
+ let fetchParams = { url, init };
+ for (const middleware of this.middleware) {
+ if (middleware.pre) {
+ fetchParams = await middleware.pre({
+ fetch: this.fetchApi,
+ ...fetchParams,
+ }) || fetchParams;
+ }
+ }
+ let response: Response | undefined = undefined;
+ try {
+ response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
+ } catch (e) {
+ for (const middleware of this.middleware) {
+ if (middleware.onError) {
+ response = await middleware.onError({
+ fetch: this.fetchApi,
+ url: fetchParams.url,
+ init: fetchParams.init,
+ error: e,
+ response: response ? response.clone() : undefined,
+ }) || response;
+ }
+ }
+ if (response === undefined) {
+ if (e instanceof Error) {
+ throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response');
+ } else {
+ throw e;
+ }
+ }
+ }
+ for (const middleware of this.middleware) {
+ if (middleware.post) {
+ response = await middleware.post({
+ fetch: this.fetchApi,
+ url: fetchParams.url,
+ init: fetchParams.init,
+ response: response.clone(),
+ }) || response;
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Create a shallow clone of `this` by constructing a new instance
+ * and then shallow cloning data members.
+ */
+ private clone(this: T): T {
+ const constructor = this.constructor as any;
+ const next = new constructor(this.configuration);
+ next.middleware = this.middleware.slice();
+ return next;
+ }
+};
+
+function isBlob(value: any): value is Blob {
+ return typeof Blob !== 'undefined' && value instanceof Blob;
+}
+
+function isFormData(value: any): value is FormData {
+ return typeof FormData !== "undefined" && value instanceof FormData;
+}
+
+export class ResponseError extends Error {
+ override name: "ResponseError" = "ResponseError";
+ constructor(public response: Response, msg?: string) {
+ super(msg);
+
+ // restore prototype chain
+ const actualProto = new.target.prototype;
+ if (Object.setPrototypeOf) {
+ Object.setPrototypeOf(this, actualProto);
+ }
+ }
+}
+
+export class FetchError extends Error {
+ override name: "FetchError" = "FetchError";
+ constructor(public cause: Error, msg?: string) {
+ super(msg);
+
+ // restore prototype chain
+ const actualProto = new.target.prototype;
+ if (Object.setPrototypeOf) {
+ Object.setPrototypeOf(this, actualProto);
+ }
+ }
+}
+
+export class RequiredError extends Error {
+ override name: "RequiredError" = "RequiredError";
+ constructor(public field: string, msg?: string) {
+ super(msg);
+
+ // restore prototype chain
+ const actualProto = new.target.prototype;
+ if (Object.setPrototypeOf) {
+ Object.setPrototypeOf(this, actualProto);
+ }
+ }
+}
+
+export const COLLECTION_FORMATS = {
+ csv: ",",
+ ssv: " ",
+ tsv: "\t",
+ pipes: "|",
+};
+
+export type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
+
+export type Json = any;
+export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
+export type HTTPHeaders = { [key: string]: string };
+export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | Set | HTTPQuery };
+export type HTTPBody = Json | FormData | URLSearchParams;
+export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody };
+export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
+
+export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise
+
+export interface FetchParams {
+ url: string;
+ init: RequestInit;
+}
+
+export interface RequestOpts {
+ path: string;
+ method: HTTPMethod;
+ headers: HTTPHeaders;
+ query?: HTTPQuery;
+ body?: HTTPBody;
+}
+
+export function querystring(params: HTTPQuery, prefix: string = ''): string {
+ return Object.keys(params)
+ .map(key => querystringSingleKey(key, params[key], prefix))
+ .filter(part => part.length > 0)
+ .join('&');
+}
+
+function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array | Set | HTTPQuery, keyPrefix: string = ''): string {
+ const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
+ if (value instanceof Array) {
+ const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
+ .join(`&${encodeURIComponent(fullKey)}=`);
+ return `${encodeURIComponent(fullKey)}=${multiValue}`;
+ }
+ if (value instanceof Set) {
+ const valueAsArray = Array.from(value);
+ return querystringSingleKey(key, valueAsArray, keyPrefix);
+ }
+ if (value instanceof Date) {
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(serializeDateTime(value))}`;
+ }
+ if (value instanceof Object) {
+ return querystring(value as HTTPQuery, fullKey);
+ }
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
+}
+
+export function exists(json: any, key: string): boolean {
+ const value = json[key];
+ return value !== null && value !== undefined;
+}
+
+/**
+ * Every generated date call site routes through these.
+ *
+ * `format: date` is a calendar date, with no time and no offset, so it is converted
+ * against the local calendar on both ends: they have to agree or the date shifts by
+ * a day. `format: date-time` is an instant and uses UTC.
+ */
+export function serializeDateTime(value: Date): string {
+ return value.toISOString();
+}
+
+export function serializeDate(value: Date): string {
+ if (isNaN(value.getTime())) {
+ throw new RangeError('Invalid time value');
+ }
+ const year = ('000' + value.getFullYear()).slice(-4);
+ const month = ('0' + (value.getMonth() + 1)).slice(-2);
+ const day = ('0' + value.getDate()).slice(-2);
+ return `${year}-${month}-${day}`;
+}
+
+
+export function parseDate(value: Date | string): Date {
+ if (value instanceof Date) {
+ return value;
+ }
+ // `new Date("2026-08-05")` would parse as UTC midnight: a different day west of UTC.
+ // Local midnight is the stated day everywhere. setFullYear avoids the 1900 offset the
+ // multi-argument constructor applies to years 0-99.
+ const fullDate = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(value));
+ if (fullDate) {
+ const year = Number(fullDate[1]);
+ const month = Number(fullDate[2]) - 1;
+ const day = Number(fullDate[3]);
+ const date = new Date(0);
+ date.setFullYear(year, month, day);
+ date.setHours(0, 0, 0, 0);
+ // Out-of-range components (or a day the local zone skipped) silently roll over,
+ // which would hand back a date the server never sent.
+ if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {
+ return new Date(NaN);
+ }
+ return date;
+ }
+ return new Date(value);
+}
+
+export function parseDateTime(value: any): Date {
+ return new Date(value);
+}
+
+export function mapValues(data: any, fn: (item: any) => any): { [key: string]: any } {
+ const result: { [key: string]: any } = {};
+ for (const key of Object.keys(data)) {
+ result[key] = fn(data[key]);
+ }
+ return result;
+}
+
+// Pass-through serializer for `any`-typed properties in form data. See #1877.
+export function anyToJSON(value: any): any {
+ return value;
+}
+
+export function canConsumeForm(consumes: Consume[]): boolean {
+ for (const consume of consumes) {
+ if (consume.contentType?.startsWith('multipart/form-data') == true) {
+ return true;
+ }
+ }
+ return false;
+}
+
+export interface Consume {
+ contentType: string;
+}
+
+export interface RequestContext {
+ fetch: FetchAPI;
+ url: string;
+ init: RequestInit;
+}
+
+export interface ResponseContext {
+ fetch: FetchAPI;
+ url: string;
+ init: RequestInit;
+ response: Response;
+}
+
+export interface ErrorContext {
+ fetch: FetchAPI;
+ url: string;
+ init: RequestInit;
+ error: unknown;
+ response?: Response;
+}
+
+export interface Middleware {
+ pre?(context: RequestContext): Promise;
+ post?(context: ResponseContext): Promise;
+ onError?(context: ErrorContext): Promise;
+}
+
+export interface ApiResponse {
+ raw: Response;
+ value(): Promise;
+}
+
+export interface ResponseTransformer {
+ (json: any): T;
+}
+
+export class JSONApiResponse {
+ constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {}
+
+ async value(): Promise {
+ return this.transformer(await this.raw.json());
+ }
+}
+
+export class VoidApiResponse {
+ constructor(public raw: Response) {}
+
+ async value(): Promise {
+ return undefined;
+ }
+}
+
+/**
+ * A Blob carrying the file name the server advertised, empty when it did not send one. It is a File
+ * wherever one can be built, and the bare Blob given a name otherwise. Same name and shape as the
+ * `typescript` generator's browser HttpFile.
+ */
+export type HttpFile = Blob & { readonly name: string };
+
+export class BlobApiResponse {
+ constructor(public raw: Response) {}
+
+ /**
+ * The body named after the Content-Disposition header, so that a download keeps the name the
+ * server gave it. A File is built from a native Blob; the Blob itself is named where there is no
+ * global File (Node.js before 20), where File cannot be constructed, or where the Blob is not the
+ * native one, as returned by an injected fetch implementation such as node-fetch, which a File
+ * would stringify instead of wrapping.
+ */
+ async value(): Promise {
+ const blob = await this.raw.blob();
+ const name = parseContentDispositionFilename(this.raw.headers) ?? '';
+ if (typeof File !== 'undefined' && blob instanceof Blob) {
+ try {
+ return new File([blob], name, { type: blob.type });
+ } catch {
+ // File cannot be constructed: name the Blob itself
+ }
+ }
+ return Object.assign(blob, { name });
+ };
+}
+
+/**
+ * The file name advertised by a Content-Disposition header (RFC 6266): the RFC 5987 encoded
+ * `filename*` parameter first, falling back to the plain `filename` when it is malformed, not UTF-8
+ * or has no usable name. Any directory part is dropped; undefined when no usable name is advertised.
+ */
+export function parseContentDispositionFilename(headers: Headers): string | undefined {
+ const params = parseHeaderParameters(headers.get('Content-Disposition') ?? '');
+ return basename(decodeExtValue(params.get('filename*'))) ?? basename(params.get('filename'));
+}
+
+/** The decoded RFC 5987 ext-value, or undefined when it is not UTF-8 or its percent-encoding is malformed. */
+function decodeExtValue(value: string | undefined): string | undefined {
+ const match = value === undefined ? null : /^utf-8'[^']*'(.*)$/i.exec(value);
+ try {
+ return match ? decodeURIComponent(match[1]) : undefined;
+ } catch {
+ return undefined;
+ }
+}
+
+/**
+ * The `name=value` parameters of a header value, consumed one at a time so that a quoted-string is
+ * taken whole, `;` included. Names are lower-cased, quoted-string values are unquoted with their
+ * backslash escapes resolved, and the first occurrence of a name wins.
+ */
+function parseHeaderParameters(value: string): Map {
+ const params = new Map();
+ const parameter = /(?:^|;)\s*([^=;]+?)\s*=\s*(?:"((?:[^"\\]|\\.)*)"?|([^;]*))/g;
+ let match: RegExpExecArray | null;
+ while ((match = parameter.exec(value)) !== null) {
+ const name = match[1].toLowerCase();
+ if (!params.has(name)) {
+ params.set(name, match[2] !== undefined ? match[2].replace(/\\(.)/g, '$1') : match[3].trim());
+ }
+ }
+ return params;
+}
+
+/** The last `/` or `\` separated segment of a file name, or undefined when it is not a file name. */
+function basename(name: string | undefined): string | undefined {
+ const base = name?.split(/[\\/]/).pop();
+ return !base || base === '.' || base === '..' ? undefined : base;
+}
+
+export class TextApiResponse {
+ constructor(public raw: Response) {}
+
+ async value(): Promise {
+ return await this.raw.text();
+ };
+}
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.esm.json b/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.esm.json
new file mode 100644
index 000000000000..2c0331cce040
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.esm.json
@@ -0,0 +1,7 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "module": "esnext",
+ "outDir": "dist/esm"
+ }
+}
diff --git a/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.json b/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.json
new file mode 100644
index 000000000000..f1d5adffdbf7
--- /dev/null
+++ b/samples/client/petstore/typescript-fetch/builds/any-of-union/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "declaration": true,
+ "target": "es6",
+ "module": "commonjs",
+ "outDir": "dist",
+ "rootDir": "src",
+ "typeRoots": [
+ "node_modules/@types"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts b/samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts
index 79bf6d115811..c040122c9a3f 100644
--- a/samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts
+++ b/samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts
@@ -43,14 +43,13 @@ export function TaggedUnionFromJSONTyped(json: any, ignoreDiscriminator: boolean
if (json == null) {
return json;
}
- if (typeof json !== 'object') {
- return json;
- }
- if (instanceOfKnown(json)) {
- return KnownFromJSONTyped(json, true);
- }
- if (instanceOfOther(json)) {
- return OtherFromJSONTyped(json, true);
+ if (typeof json === 'object') {
+ if (instanceOfKnown(json)) {
+ return KnownFromJSONTyped(json, true);
+ }
+ if (instanceOfOther(json)) {
+ return OtherFromJSONTyped(json, true);
+ }
}
return {} as any;
}
@@ -63,14 +62,13 @@ export function TaggedUnionToJSONTyped(value?: TaggedUnion | null, ignoreDiscrim
if (value == null) {
return value;
}
- if (typeof value !== 'object') {
- return value;
- }
- if (instanceOfKnown(value)) {
- return KnownToJSON(value as Known);
- }
- if (instanceOfOther(value)) {
- return OtherToJSON(value as Other);
+ if (typeof value === 'object') {
+ if (instanceOfKnown(value)) {
+ return KnownToJSON(value as Known);
+ }
+ if (instanceOfOther(value)) {
+ return OtherToJSON(value as Other);
+ }
}
return {};
}
diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts
index af3bbd2a6269..378b1b6771ad 100644
--- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts
+++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts
@@ -44,7 +44,7 @@ export function TestArrayResponseFromJSONTyped(json: any, ignoreDiscriminator: b
return json;
}
if (Array.isArray(json)) {
- if (json.every(item => typeof item === 'object')) {
+ if (json.every(item => item !== null && typeof item === 'object')) {
if (json.every(item => instanceOfTestA(item))) {
return json.map(value => TestAFromJSONTyped(value, true));
}
@@ -73,7 +73,7 @@ export function TestArrayResponseToJSONTyped(value?: TestArrayResponse | null, i
return value;
}
if (Array.isArray(value)) {
- if (value.every(item => typeof item === 'object')) {
+ if (value.every(item => item !== null && typeof item === 'object')) {
if (value.every(item => instanceOfTestA(item))) {
return value.map(value => TestAToJSON(value as TestA));
}
diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestResponse.ts
index ca45996d992e..bbcfec3b4397 100644
--- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestResponse.ts
+++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestResponse.ts
@@ -43,14 +43,13 @@ export function TestResponseFromJSONTyped(json: any, ignoreDiscriminator: boolea
if (json == null) {
return json;
}
- if (typeof json !== 'object') {
- return json;
- }
- if (instanceOfTestA(json)) {
- return TestAFromJSONTyped(json, true);
- }
- if (instanceOfTestB(json)) {
- return TestBFromJSONTyped(json, true);
+ if (typeof json === 'object') {
+ if (instanceOfTestA(json)) {
+ return TestAFromJSONTyped(json, true);
+ }
+ if (instanceOfTestB(json)) {
+ return TestBFromJSONTyped(json, true);
+ }
}
if (typeof json === 'string') {
return json;
@@ -66,14 +65,13 @@ export function TestResponseToJSONTyped(value?: TestResponse | null, ignoreDiscr
if (value == null) {
return value;
}
- if (typeof value !== 'object') {
- return value;
- }
- if (instanceOfTestA(value)) {
- return TestAToJSON(value as TestA);
- }
- if (instanceOfTestB(value)) {
- return TestBToJSON(value as TestB);
+ if (typeof value === 'object') {
+ if (instanceOfTestA(value)) {
+ return TestAToJSON(value as TestA);
+ }
+ if (instanceOfTestB(value)) {
+ return TestBToJSON(value as TestB);
+ }
}
if (typeof value === 'string') {
return value;