Skip to content

Commit b112c18

Browse files
committed
[typescript-angular] Fix inner enum reference in multi-map property type
Fixes #22747
1 parent 3be911d commit b112c18

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,31 @@ private String applyLocalTypeMapping(String type) {
406406
return type;
407407
}
408408

409+
@Override
410+
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
411+
super.postProcessModelProperty(model, property);
412+
if (property.isInnerEnum && property.items != null && property.enumName != null) {
413+
// Fix maps/arrays of inner enums to use the correct enum name.
414+
// The DefaultCodegen.updateDataTypeWithEnumForMap uses toEnumName(innerItem) which
415+
// returns a name based on the inner item's name (e.g., "InnerEnum" for "inner").
416+
// But the generated TypeScript enum uses property.enumName (e.g., "RuleMsgOperationReportingOptionsEnum").
417+
// We replace the wrong inner enum name with the correct property enum name.
418+
// The classname prefix will be added later by postProcessModels in AbstractTypeScriptClientCodegen.
419+
CodegenProperty innerMostItem = property.items;
420+
while (innerMostItem != null && (Boolean.TRUE.equals(innerMostItem.isMap)
421+
|| Boolean.TRUE.equals(innerMostItem.isArray))) {
422+
innerMostItem = innerMostItem.items;
423+
}
424+
if (innerMostItem != null && innerMostItem.enumName != null
425+
&& !innerMostItem.enumName.equals(property.enumName)) {
426+
// Replace the wrong enum name with the correct one (without classname prefix)
427+
property.datatypeWithEnum = property.datatypeWithEnum.replace(
428+
innerMostItem.enumName, property.enumName);
429+
property.dataType = property.datatypeWithEnum;
430+
}
431+
}
432+
}
433+
409434
@Override
410435
public void postProcessParameter(CodegenParameter parameter) {
411436
super.postProcessParameter(parameter);

modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,4 +489,40 @@ public void testDeepObject() throws IOException {
489489
assertThat(fileContents).containsSubsequence("'options',\n", "<any>options,\n", "QueryParamStyle.DeepObject,\n", "true,\n");
490490
assertThat(fileContents).containsSubsequence("'inputOptions',\n", "<any>inputOptions,\n", "QueryParamStyle.DeepObject,\n", "true,\n");
491491
}
492+
493+
@Test
494+
public void testMapWithArrayOfEnumsUsesCorrectEnumName() throws IOException {
495+
// GIVEN - a schema with a map property containing an array of enums
496+
// This tests the fix for the issue where maps with array of enums generated
497+
// "InnerEnum" type reference instead of the correct qualified enum name.
498+
final String specPath = "src/test/resources/3_0/issue_19393_map_of_inner_enum.yaml";
499+
500+
File output = Files.createTempDirectory("test").toFile();
501+
output.deleteOnExit();
502+
503+
// WHEN
504+
final CodegenConfigurator configurator = new CodegenConfigurator()
505+
.setGeneratorName("typescript-angular")
506+
.setInputSpec(specPath)
507+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
508+
509+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
510+
511+
Generator generator = new DefaultGenerator();
512+
generator.opts(clientOptInput).generate();
513+
514+
// THEN - verify the map property uses the correct qualified enum name, not "InnerEnum"
515+
final String fileContents = Files.readString(Paths.get(output + "/model/employeeWithMultiMapOfEnum.ts"));
516+
517+
// The property type should use the correctly qualified enum name
518+
// Note: the test spec uses uniqueItems: true so Set is used instead of Array
519+
assertThat(fileContents).contains("projectRoles?: { [key: string]: Set<EmployeeWithMultiMapOfEnum.ProjectRolesEnum>; }");
520+
521+
// Should NOT contain the incorrect "InnerEnum" reference
522+
assertThat(fileContents).doesNotContain("InnerEnum");
523+
524+
// The enum should be defined in the namespace
525+
assertThat(fileContents).contains("export const ProjectRolesEnum = {");
526+
assertThat(fileContents).contains("export type ProjectRolesEnum = typeof ProjectRolesEnum[keyof typeof ProjectRolesEnum];");
527+
}
492528
}

0 commit comments

Comments
 (0)