From e286ada2f346c6b8d50129638bb183bb333877ee Mon Sep 17 00:00:00 2001
From: Bodo Graumann <mail@bodograumann.de>
Date: Sun, 12 Jan 2020 14:46:29 +0100
Subject: [PATCH 1/4] Add failing tests for typescript type declaration

---
 .../TypeScriptFetchClientCodegenTest.java     | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)

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 a72a93de9d81..f6b0678a4147 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
@@ -1,9 +1,11 @@
 package org.openapitools.codegen.typescript.fetch;
 
 import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.*;
 import org.openapitools.codegen.CodegenConstants;
 import org.openapitools.codegen.TestUtils;
 import org.openapitools.codegen.languages.TypeScriptFetchClientCodegen;
+import org.openapitools.codegen.utils.ModelUtils;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -69,4 +71,35 @@ public void toVarName() {
         Assert.assertEquals(codegen.toVarName("valid_var"), "valid_var");
     }
 
+    @Test
+    public void getTypeDeclarationTest() {
+        Schema<?> childSchema = new ArraySchema().items(new StringSchema());
+
+        OpenAPI api = TestUtils.createOpenAPI();
+        api.getComponents().addSchemas("Child", childSchema);
+
+        TypeScriptFetchClientCodegen codegen = new TypeScriptFetchClientCodegen();
+        codegen.setOpenAPI(api);
+
+        // Cf. issue #4968: Array of Alias of Array
+        Schema<?> parentSchema = new ArraySchema().items(
+            new Schema().$ref("#/components/schemas/Child")
+        );
+
+        ModelUtils.setGenerateAliasAsModel(false);
+        Assert.assertEquals(codegen.getTypeDeclaration(parentSchema), "Array<Array<string>>");
+
+        ModelUtils.setGenerateAliasAsModel(true);
+        Assert.assertEquals(codegen.getTypeDeclaration(parentSchema), "Array<Child>");
+
+        // Same for Map
+        parentSchema = new MapSchema().additionalProperties(new Schema().$ref("#/components/schemas/Child"));
+
+        ModelUtils.setGenerateAliasAsModel(false);
+        Assert.assertEquals(codegen.getTypeDeclaration(parentSchema), "{ [key: string]: Array<string>; }");
+
+        ModelUtils.setGenerateAliasAsModel(true);
+        Assert.assertEquals(codegen.getTypeDeclaration(parentSchema), "{ [key: string]: Child; }");
+    }
+
 }

From 5a247d30a2cc360fb10b09618d8d1e2c84a272ba Mon Sep 17 00:00:00 2001
From: Bodo Graumann <mail@bodograumann.de>
Date: Sun, 12 Jan 2020 14:55:30 +0100
Subject: [PATCH 2/4] Refactor array and map child type string fallback

---
 .../openapitools/codegen/DefaultCodegen.java  | 34 ++++++++-----------
 .../languages/AbstractJavaCodegen.java        |  7 +---
 2 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
index 73c6a6931091..ae1328ec7062 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
@@ -1734,12 +1734,23 @@ public String getSchemaType(Schema schema) {
     }
 
     protected Schema<?> getSchemaItems(ArraySchema schema) {
-        if (schema.getItems() != null) {
-            return schema.getItems();
-        } else {
+        Schema<?> items = schema.getItems();
+        if (items == null) {
             LOGGER.error("Undefined array inner type for `{}`. Default to String.", schema.getName());
-            return new StringSchema().description("TODO default missing array inner type to string");
+            items = new StringSchema().description("TODO default missing array inner type to string");
+            schema.setItems(items);
         }
+        return items;
+    }
+
+    protected Schema<?> getSchemaAdditionalProperties(Schema schema) {
+        Schema<?> inner = ModelUtils.getAdditionalProperties(schema);
+        if (inner == null) {
+            LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", schema.getName());
+            inner = new StringSchema().description("TODO default missing map inner type to string");
+            schema.setAdditionalProperties(inner);
+        }
+        return inner;
     }
 
     /**
@@ -2534,9 +2545,6 @@ public CodegenProperty fromProperty(String name, Schema p) {
             // default to string if inner item is undefined
             ArraySchema arraySchema = (ArraySchema) p;
             Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema), importMapping);
-            if (arraySchema.getItems() == null) {
-                arraySchema.setItems(innerSchema);
-            }
         } else if (ModelUtils.isMapSchema(p)) {
             Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getAdditionalProperties(p),
                     importMapping);
@@ -2616,9 +2624,6 @@ public CodegenProperty fromProperty(String name, Schema p) {
             }
             ArraySchema arraySchema = (ArraySchema) p;
             Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema), importMapping);
-            if (arraySchema.getItems() == null) {
-                arraySchema.setItems(innerSchema);
-            }
             CodegenProperty cp = fromProperty(itemName, innerSchema);
             updatePropertyForArray(property, cp);
         } else if (ModelUtils.isMapSchema(p)) {
@@ -3499,9 +3504,6 @@ public CodegenParameter fromParameter(Parameter parameter, Set<String> imports)
             if (ModelUtils.isArraySchema(parameterSchema)) { // for array parameter
                 final ArraySchema arraySchema = (ArraySchema) parameterSchema;
                 Schema inner = getSchemaItems(arraySchema);
-                if (arraySchema.getItems() == null) {
-                    arraySchema.setItems(inner);
-                }
 
                 collectionFormat = getCollectionFormat(parameter);
                 // default to csv:
@@ -5098,9 +5100,6 @@ public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body,
                 if (ModelUtils.isArraySchema(s)) {
                     final ArraySchema arraySchema = (ArraySchema) s;
                     Schema inner = getSchemaItems(arraySchema);
-                    if (arraySchema.getItems() == null) {
-                        arraySchema.setItems(inner);
-                    }
 
                     codegenParameter = fromFormProperty(entry.getKey(), inner, imports);
                     CodegenProperty codegenProperty = fromProperty("inner", inner);
@@ -5300,9 +5299,6 @@ public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, S
         } else if (ModelUtils.isArraySchema(schema)) {
             final ArraySchema arraySchema = (ArraySchema) schema;
             Schema inner = getSchemaItems(arraySchema);
-            if (arraySchema.getItems() == null) {
-                arraySchema.setItems(inner);
-            }
             CodegenProperty codegenProperty = fromProperty("property", arraySchema);
             imports.add(codegenProperty.baseType);
             CodegenProperty innerCp = codegenProperty;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java
index fdd625e88390..66c2219ffd0c 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java
@@ -740,12 +740,7 @@ public String getTypeDeclaration(Schema p) {
             Schema<?> items = getSchemaItems((ArraySchema) p);
             return getSchemaType(p) + "<" + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, items)) + ">";
         } else if (ModelUtils.isMapSchema(p)) {
-            Schema inner = ModelUtils.getAdditionalProperties(p);
-            if (inner == null) {
-                LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", p.getName());
-                inner = new StringSchema().description("TODO default missing map inner type to string");
-                p.setAdditionalProperties(inner);
-            }
+            Schema<?> inner = getSchemaAdditionalProperties(p);
             return getSchemaType(p) + "<String, " + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, inner)) + ">";
         }
         return super.getTypeDeclaration(p);

From 87b78cdc06dd7015993b062943ecbe88028be5d3 Mon Sep 17 00:00:00 2001
From: Bodo Graumann <mail@bodograumann.de>
Date: Sun, 12 Jan 2020 14:56:35 +0100
Subject: [PATCH 3/4] Add unaliasSchema to typescript getTypeDeclaration

---
 .../languages/AbstractTypeScriptClientCodegen.java       | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java
index 39240bfd46b8..8bc11a662232 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java
@@ -378,13 +378,12 @@ public String toModelFilename(String name) {
     @Override
     public String getTypeDeclaration(Schema p) {
         if (ModelUtils.isArraySchema(p)) {
-            ArraySchema ap = (ArraySchema) p;
-            Schema inner = ap.getItems();
-            return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
+            Schema<?> items = getSchemaItems((ArraySchema) p);
+            return getSchemaType(p) + "<" + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, items)) + ">";
         } else if (ModelUtils.isMapSchema(p)) {
-            Schema inner = ModelUtils.getAdditionalProperties(p);
+            Schema<?> inner = getSchemaAdditionalProperties(p);
             String nullSafeSuffix = getNullSafeAdditionalProps() ? " | undefined" : "";
-            return "{ [key: string]: " + getTypeDeclaration(inner) + nullSafeSuffix + "; }";
+            return "{ [key: string]: " + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, inner)) + nullSafeSuffix  + "; }";
         } else if (ModelUtils.isFileSchema(p)) {
             return "any";
         } else if (ModelUtils.isBinarySchema(p)) {

From 2bace33429f0ada762e181d5f74e851c56714948 Mon Sep 17 00:00:00 2001
From: Bodo Graumann <mail@bodograumann.de>
Date: Mon, 2 Mar 2020 11:57:26 +0100
Subject: [PATCH 4/4] TypeScriptRxjs: Use Blob as file type declaration

This was inadvertantly changed in
https://github.com/OpenAPITools/openapi-generator/pull/5266
---
 .../codegen/languages/TypeScriptRxjsClientCodegen.java        | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
index fbcad1bc8048..2d00d6b30a01 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
@@ -107,7 +107,9 @@ public boolean isDataTypeFile(final String dataType) {
 
     @Override
     public String getTypeDeclaration(Schema p) {
-        if (ModelUtils.isBinarySchema(p)) {
+        if (ModelUtils.isFileSchema(p)) {
+            return "Blob";
+        } else if (ModelUtils.isBinarySchema(p)) {
             return "Blob";
         }
         return super.getTypeDeclaration(p);