Skip to content

Commit

Permalink
Possibility to map Java Map as TypeScript Record (#706)
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtechhabarta committed Feb 23, 2022
1 parent 0188fd0 commit c19d407
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

package cz.habarta.typescript.generator;


public enum MapMapping {
asIndexedArray, asRecord
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public class Settings {
public Map<String, String> customTypeAliases = new LinkedHashMap<>();
private List<CustomTypeAlias> validatedCustomTypeAliases = null;
public DateMapping mapDate; // default is DateMapping.asDate
public MapMapping mapMap; // default is MapMapping.asIndexedArray
public EnumMapping mapEnum; // default is EnumMapping.asUnion
public IdentifierCasing enumMemberCasing; // default is IdentifierCasing.keepOriginal
public boolean nonConstEnums = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import cz.habarta.typescript.generator.EnumMapping;
import cz.habarta.typescript.generator.Extension;
import cz.habarta.typescript.generator.IdentifierCasing;
import cz.habarta.typescript.generator.MapMapping;
import cz.habarta.typescript.generator.NullabilityDefinition;
import cz.habarta.typescript.generator.OptionalPropertiesDeclaration;
import cz.habarta.typescript.generator.RestNamespacing;
Expand Down Expand Up @@ -150,6 +151,9 @@ public TsModel javaToTypeScript(Model model) {
}
}

// dates
tsModel = transformMaps(symbolTable, tsModel);

// dates
tsModel = transformDates(symbolTable, tsModel);

Expand Down Expand Up @@ -841,6 +845,23 @@ private static TsTemplateLiteral processPathTemplate(PathTemplate pathTemplate)
return new TsTaggedTemplateLiteral(new TsIdentifierReference("uriEncoding"), spans);
}

private TsModel transformMaps(SymbolTable symbolTable, TsModel tsModel) {
if (settings.mapMap != MapMapping.asRecord) {
return tsModel;
}
final TsModel model = transformBeanPropertyTypes(tsModel, new TsType.Transformer() {
@Override
public TsType transform(TsType.Context context, TsType type) {
if (type instanceof TsType.IndexedArrayType) {
final TsType.IndexedArrayType indexedArrayType = (TsType.IndexedArrayType) type;
return new TsType.GenericBasicType("Record", indexedArrayType.indexType, indexedArrayType.elementType);
}
return type;
}
});
return model;
}

private TsModel transformDates(SymbolTable symbolTable, TsModel tsModel) {
final TsAliasModel dateAsNumber = new TsAliasModel(null, symbolTable.getSyntheticSymbol("DateAsNumber"), null, TsType.Number, null);
final TsAliasModel dateAsString = new TsAliasModel(null, symbolTable.getSyntheticSymbol("DateAsString"), null, TsType.String, null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

package cz.habarta.typescript.generator;

import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;


public class MapTest {

public static class ClassWithMap {
public Map<String, Person> people;
}

@Test
public void testDefault() {
final Settings settings = TestUtils.settings();
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(ClassWithMap.class));
Assertions.assertTrue(output.contains("people: { [index: string]: Person }"));
}

@Test
public void testIndexedArray() {
final Settings settings = TestUtils.settings();
settings.mapMap = MapMapping.asIndexedArray;
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(ClassWithMap.class));
Assertions.assertTrue(output.contains("people: { [index: string]: Person }"));
}

@Test
public void testRecord() {
final Settings settings = TestUtils.settings();
settings.mapMap = MapMapping.asRecord;
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(ClassWithMap.class));
Assertions.assertTrue(output.contains("people: Record<string, Person>"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import cz.habarta.typescript.generator.JsonLibrary;
import cz.habarta.typescript.generator.JsonbConfiguration;
import cz.habarta.typescript.generator.Logger;
import cz.habarta.typescript.generator.MapMapping;
import cz.habarta.typescript.generator.ModuleDependency;
import cz.habarta.typescript.generator.NullabilityDefinition;
import cz.habarta.typescript.generator.OptionalProperties;
Expand Down Expand Up @@ -79,6 +80,7 @@ public class GenerateTask extends DefaultTask {
public List<String> customTypeMappings;
public List<String> customTypeAliases;
public DateMapping mapDate;
public MapMapping mapMap;
public EnumMapping mapEnum;
public IdentifierCasing enumMemberCasing;
public boolean nonConstEnums;
Expand Down Expand Up @@ -168,6 +170,7 @@ private Settings createSettings(URLClassLoader classLoader) {
settings.customTypeMappings = Settings.convertToMap(customTypeMappings, "customTypeMapping");
settings.customTypeAliases = Settings.convertToMap(customTypeAliases, "customTypeAlias");
settings.mapDate = mapDate;
settings.mapMap = mapMap;
settings.mapEnum = mapEnum;
settings.enumMemberCasing = enumMemberCasing;
settings.nonConstEnums = nonConstEnums;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import cz.habarta.typescript.generator.JsonLibrary;
import cz.habarta.typescript.generator.JsonbConfiguration;
import cz.habarta.typescript.generator.Logger;
import cz.habarta.typescript.generator.MapMapping;
import cz.habarta.typescript.generator.ModuleDependency;
import cz.habarta.typescript.generator.NullabilityDefinition;
import cz.habarta.typescript.generator.OptionalProperties;
Expand Down Expand Up @@ -421,6 +422,18 @@ public class GenerateMojo extends AbstractMojo {
@Parameter
private DateMapping mapDate;

/**
* Specifies how {@link java.util.Map} and similar types will be mapped.
* Supported values are:
* <ul>
* <li><code>asIndexedArray</code> - creates <a href="https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures">indexed array type</a>, example: <code>{ [index: string]: Person }</code> (original way)</li>
* <li><code>asRecord</code> - creates <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type">Record type</a>, example: <code>Record&lt;string, Person&gt;</code> (from TypeScript 2.1)</li>
* </ul>
* Default value is <code>asIndexedArray</code>.<br>
*/
@Parameter
private MapMapping mapMap;

/**
* Specifies how enums will be mapped.
* Supported values are:
Expand Down Expand Up @@ -926,6 +939,7 @@ private Settings createSettings(URLClassLoader classLoader) {
settings.customTypeMappings = Settings.convertToMap(customTypeMappings, "customTypeMapping");
settings.customTypeAliases = Settings.convertToMap(customTypeAliases, "customTypeAlias");
settings.mapDate = mapDate;
settings.mapMap = mapMap;
settings.mapEnum = mapEnum;
settings.enumMemberCasing = enumMemberCasing;
settings.nonConstEnums = nonConstEnums;
Expand Down

0 comments on commit c19d407

Please sign in to comment.