diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java index 8190aa46c700..8ebebbf4f485 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java @@ -406,6 +406,31 @@ private String applyLocalTypeMapping(String type) { return type; } + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + if (property.isInnerEnum && property.items != null && property.enumName != null) { + // Fix maps/arrays of inner enums to use the correct enum name. + // The DefaultCodegen.updateDataTypeWithEnumForMap uses toEnumName(innerItem) which + // returns a name based on the inner item's name (e.g., "InnerEnum" for "inner"). + // But the generated TypeScript enum uses property.enumName (e.g., "RuleMsgOperationReportingOptionsEnum"). + // We replace the wrong inner enum name with the correct property enum name. + // The classname prefix will be added later by postProcessModels in AbstractTypeScriptClientCodegen. + CodegenProperty innerMostItem = property.items; + while (innerMostItem != null && (Boolean.TRUE.equals(innerMostItem.isMap) + || Boolean.TRUE.equals(innerMostItem.isArray))) { + innerMostItem = innerMostItem.items; + } + if (innerMostItem != null && innerMostItem.enumName != null + && !innerMostItem.enumName.equals(property.enumName)) { + // Replace the wrong enum name with the correct one (without classname prefix) + property.datatypeWithEnum = property.datatypeWithEnum.replace( + innerMostItem.enumName, property.enumName); + property.dataType = property.datatypeWithEnum; + } + } + } + @Override public void postProcessParameter(CodegenParameter parameter) { super.postProcessParameter(parameter); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java index 7d7de3a8840e..3b7ad57e2e1f 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java @@ -489,4 +489,40 @@ public void testDeepObject() throws IOException { assertThat(fileContents).containsSubsequence("'options',\n", "options,\n", "QueryParamStyle.DeepObject,\n", "true,\n"); assertThat(fileContents).containsSubsequence("'inputOptions',\n", "inputOptions,\n", "QueryParamStyle.DeepObject,\n", "true,\n"); } + + @Test + public void testMapWithArrayOfEnumsUsesCorrectEnumName() throws IOException { + // GIVEN - a schema with a map property containing an array of enums + // This tests the fix for the issue where maps with array of enums generated + // "InnerEnum" type reference instead of the correct qualified enum name. + final String specPath = "src/test/resources/3_0/issue_19393_map_of_inner_enum.yaml"; + + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + // WHEN + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-angular") + .setInputSpec(specPath) + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + + Generator generator = new DefaultGenerator(); + generator.opts(clientOptInput).generate(); + + // THEN - verify the map property uses the correct qualified enum name, not "InnerEnum" + final String fileContents = Files.readString(Paths.get(output + "/model/employeeWithMultiMapOfEnum.ts")); + + // The property type should use the correctly qualified enum name + // Note: the test spec uses uniqueItems: true so Set is used instead of Array + assertThat(fileContents).contains("projectRoles?: { [key: string]: Set; }"); + + // Should NOT contain the incorrect "InnerEnum" reference + assertThat(fileContents).doesNotContain("InnerEnum"); + + // The enum should be defined in the namespace + assertThat(fileContents).contains("export const ProjectRolesEnum = {"); + assertThat(fileContents).contains("export type ProjectRolesEnum = typeof ProjectRolesEnum[keyof typeof ProjectRolesEnum];"); + } }