Skip to content

Commit 3e7fcb5

Browse files
author
k.golikov
committed
Json-To-TypeScript: add tuple support (unstable)
1 parent 5812adb commit 3e7fcb5

File tree

8 files changed

+72
-26
lines changed

8 files changed

+72
-26
lines changed

src/pages/jsonToTypeScriptPage/JsonToTypeScriptPage.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ const JsonToTypeScriptPage = () => {
9494
} catch (e) {
9595
setError(getErrorMessage(e));
9696

97-
return noResult;
97+
if (e instanceof SyntaxError) {
98+
return noResult;
99+
} else {
100+
throw e;
101+
}
98102
}
99103
},
100104
[json, conversionOptions],

src/pages/jsonToTypeScriptPage/components/JsonToTypeScriptSettings.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { Dispatch, FunctionComponent, SetStateAction } from 'react';
22
import JsonToTypeScriptConversionSelectableOptions, {
33
NameTransformer
44
} from '../types/JsonToTypeScriptConversionSelectableOptions';
5-
import { Button, Col, Input, Select, Switch, Tooltip } from 'antd';
5+
import { Button, Col, Input, Select, Switch, Tag } from 'antd';
66
import useChangeStateHandler from '../../../hooks/useChangeStateHandler';
77
import styles from './JsonToTypeScriptSettings.module.scss';
88
import ExportType from '../types/ExportType';
@@ -88,13 +88,13 @@ const JsonToTypeScriptSettings: FunctionComponent<Props> = ({ options, setOption
8888
</label>
8989

9090
<label className={classNames('mt-1', styles.formItem)}>
91-
<Switch checked={options.isTuplesEnabled} onChange={handleOptionChange('isTuplesEnabled')} disabled />
92-
<Tooltip title="Coming soon" placement="bottom">
93-
<Text className="ms-3" type="secondary">
94-
Enable tuples
95-
{/*<Text italic type="secondary" className="ms-2">Coming soon</Text>*/}
96-
</Text>
97-
</Tooltip>
91+
<Switch checked={options.isTuplesEnabled} onChange={handleOptionChange('isTuplesEnabled')} />
92+
<Text className="ms-3">
93+
Enable tuples{' '}
94+
<Tag color="warning" className="ms-1">
95+
unstable
96+
</Tag>
97+
</Text>
9898
</label>
9999
</Col>
100100
);

src/pages/jsonToTypeScriptPage/types/typescript.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,17 @@ export class TypeScriptArray implements ITypeScriptType {
105105
}
106106
}
107107

108-
export class TypeScriptUnion implements ITypeScriptType {
108+
export abstract class TypeScriptTypesCombination implements ITypeScriptType {
109+
protected constructor(public name: string, public readonly types: TypeScriptType[]) {}
110+
111+
abstract stringifyReference(): string;
112+
}
113+
114+
export class TypeScriptUnion extends TypeScriptTypesCombination {
109115
//, IDeclarableTypeScriptType {
110-
public constructor(public name: string, public readonly types: TypeScriptType[]) {}
116+
public constructor(public name: string, public readonly types: TypeScriptType[]) {
117+
super(name, types);
118+
}
111119

112120
// stringifyDeclaration(exportType?: ExportType): string {
113121
// return `${getExportKeyword(exportType)}type ${this.name} = ${this.stringifyDeclarationBody()};`;
@@ -123,8 +131,10 @@ export class TypeScriptUnion implements ITypeScriptType {
123131
}
124132

125133
//TODO add tuples support
126-
export class TypeScriptTuple implements ITypeScriptType {
127-
public constructor(public name: string, public readonly types: TypeScriptType[]) {}
134+
export class TypeScriptTuple extends TypeScriptTypesCombination {
135+
public constructor(public name: string, public readonly types: TypeScriptType[]) {
136+
super(name, types);
137+
}
128138

129139
stringifyDeclarationBody(): string {
130140
return '[' + this.types.map(getTypeScriptTypeReference).join(', ') + ']';
@@ -140,6 +150,7 @@ export type TypeScriptType =
140150
| TypeScriptInterface
141151
| TypeScriptArray
142152
| TypeScriptUnion
153+
| TypeScriptTuple
143154
| TypeScriptUnknown;
144155

145156
const getExportKeyword = (exportType: ExportType = ExportType.NONE) => {

src/pages/jsonToTypeScriptPage/utils/getAllTypeScriptTypeInnerDeclarableTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
IDeclarableTypeScriptType,
44
TypeScriptArray,
55
TypeScriptType,
6-
TypeScriptUnion,
6+
TypeScriptTypesCombination,
77
TypeScriptUnknown
88
} from '../types/typescript';
99
import { isObject, isString } from 'lodash';
@@ -19,7 +19,7 @@ const getAllTypeScriptTypeInnerDeclarableTypes = (
1919
return []; //getTypeScriptTypeDeclaration(type, name, exportType)
2020
}
2121

22-
if (type instanceof TypeScriptUnion) {
22+
if (type instanceof TypeScriptTypesCombination) {
2323
return type.types.flatMap((innerType) => getAllTypeScriptTypeInnerDeclarableTypes(innerType, options, true));
2424
}
2525

src/pages/jsonToTypeScriptPage/utils/getJsonType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { chain, isArray, isBoolean, isNil, isObject, isString, mapValues } from
44
const getJsonType = (object: unknown): JsonType => {
55
if (isObject(object)) {
66
if (isArray(object)) {
7-
return new JsonArray(chain(object).map(getJsonType).uniq().value()); //TODO remove `uniq` here?
7+
return new JsonArray(chain(object).map(getJsonType).value());
88
}
99

1010
return new JsonObject(

src/pages/jsonToTypeScriptPage/utils/getTypeScriptType.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { JsonArray, JsonType } from '../types/json';
2-
import { TypeScriptArray, TypeScriptInterface, TypeScriptObjectField, TypeScriptType } from '../types/typescript';
2+
import {
3+
TypeScriptArray,
4+
TypeScriptInterface,
5+
TypeScriptObjectField,
6+
TypeScriptTuple,
7+
TypeScriptType,
8+
TypeScriptUnknown
9+
} from '../types/typescript';
310
import { chain, isString } from 'lodash';
411
import { singular } from 'pluralize';
512
import getMergedTypeScriptTypes from './mergeTypeScriptTypesList';
@@ -23,10 +30,25 @@ const getTypeScriptType = (
2330
}
2431

2532
if (jsonType instanceof JsonArray) {
26-
const typeScriptTypes = jsonType.types.map((type) => getTypeScriptType(arrayElementName, type, options));
27-
const mergedTypeScriptTypes = getMergedTypeScriptTypes(typeScriptTypes);
33+
if (options.isTuplesEnabled) {
34+
if (jsonType.types.length === 0) {
35+
return new TypeScriptTuple('', []);
36+
}
2837

29-
return new TypeScriptArray(mergedTypeScriptTypes);
38+
const typeScriptTypes = jsonType.types.map((type) => getTypeScriptType(arrayElementName, type, options));
39+
// const mergedType = getMergedTypeScriptTypes(typeScriptTypes, options);
40+
41+
return new TypeScriptTuple(arrayElementName, typeScriptTypes);
42+
} else {
43+
if (jsonType.types.length === 0) {
44+
return new TypeScriptArray(new TypeScriptUnknown());
45+
}
46+
47+
const typeScriptTypes = jsonType.types.map((type) => getTypeScriptType(arrayElementName, type, options));
48+
const mergedType = getMergedTypeScriptTypes(typeScriptTypes, options);
49+
50+
return new TypeScriptArray(mergedType);
51+
}
3052
}
3153

3254
return new TypeScriptInterface(

src/pages/jsonToTypeScriptPage/utils/mergeTypeScriptTypes.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ import {
77
TypeScriptUnion
88
} from '../types/typescript';
99
import getTypeScriptUnion from './getTypeScriptUnion';
10+
import JsonToTypeScriptConversionOptions from '../types/JsonToTypeScriptConversionOptions';
1011

11-
const mergeTypeScriptTypes = (a: TypeScriptType, b: TypeScriptType): TypeScriptType => {
12+
const mergeTypeScriptTypes = (
13+
a: TypeScriptType,
14+
b: TypeScriptType,
15+
options: JsonToTypeScriptConversionOptions
16+
): TypeScriptType => {
1217
const singleType = a;
1318
const bothTypes = getTypeScriptUnion('', [a, b]);
1419

@@ -49,7 +54,7 @@ const mergeTypeScriptTypes = (a: TypeScriptType, b: TypeScriptType): TypeScriptT
4954

5055
const isOptional = aField.isOptional || bField.isOptional;
5156

52-
const mergedFieldType = mergeTypeScriptTypes(aField.type, bField.type);
57+
const mergedFieldType = mergeTypeScriptTypes(aField.type, bField.type, options);
5358

5459
result[fieldKey] = new TypeScriptObjectField(mergedFieldType, isOptional);
5560
return result;
@@ -60,7 +65,7 @@ const mergeTypeScriptTypes = (a: TypeScriptType, b: TypeScriptType): TypeScriptT
6065
}
6166

6267
if (a instanceof TypeScriptArray && b instanceof TypeScriptArray) {
63-
const mergedTypes = mergeTypeScriptTypes(a.type, b.type);
68+
const mergedTypes = mergeTypeScriptTypes(a.type, b.type, options);
6469
return new TypeScriptArray(mergedTypes);
6570
}
6671

@@ -89,7 +94,7 @@ const mergeTypeScriptTypes = (a: TypeScriptType, b: TypeScriptType): TypeScriptT
8994
}
9095

9196
const unionObject = union.types[unionSameTypeIndex];
92-
union.types[unionSameTypeIndex] = mergeTypeScriptTypes(unionObject, notUnion);
97+
union.types[unionSameTypeIndex] = mergeTypeScriptTypes(unionObject, notUnion, options);
9398
return union;
9499
}
95100

src/pages/jsonToTypeScriptPage/utils/mergeTypeScriptTypesList.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { TypeScriptType } from '../types/typescript';
22
import mergeTypeScriptTypes from './mergeTypeScriptTypes';
3+
import JsonToTypeScriptConversionOptions from '../types/JsonToTypeScriptConversionOptions';
34

45
//TODO
5-
const getMergedTypeScriptTypes = (types: TypeScriptType[]): TypeScriptType => {
6+
const getMergedTypeScriptTypes = (
7+
types: TypeScriptType[],
8+
options: JsonToTypeScriptConversionOptions
9+
): TypeScriptType => {
610
return types.reduce((result, value) => {
711
if (result === undefined) {
812
return value;
913
}
1014

11-
return mergeTypeScriptTypes(result, value);
15+
return mergeTypeScriptTypes(result, value, options);
1216
}, undefined as unknown as TypeScriptType);
1317
};
1418

0 commit comments

Comments
 (0)