typia 3.5.0-dev.20230212 → 3.5.0-dev.20230213

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.CloneTransformer = void 0;
18
+ var typescript_1 = __importDefault(require("typescript"));
19
+ var CloneProgrammer_1 = require("../../../programmers/CloneProgrammer");
20
+ var CloneTransformer;
21
+ (function (CloneTransformer) {
22
+ function transform(project, modulo, expression) {
23
+ if (expression.arguments.length !== 1)
24
+ throw new Error("Error on typia.clone(): no input value.");
25
+ var type = expression.typeArguments && expression.typeArguments[0]
26
+ ? project.checker.getTypeFromTypeNode(expression.typeArguments[0])
27
+ : project.checker.getTypeAtLocation(expression.arguments[0]);
28
+ if (type.isTypeParameter())
29
+ throw new Error("Error on typia.clone(): non-specified generic argument.");
30
+ return typescript_1.default.factory.createCallExpression(CloneProgrammer_1.CloneProgrammer.generate(__assign(__assign({}, project), { options: __assign(__assign({}, project.options), { functional: false, numeric: false }) }), modulo)(type), undefined, [expression.arguments[0]]);
31
+ }
32
+ CloneTransformer.transform = transform;
33
+ })(CloneTransformer = exports.CloneTransformer || (exports.CloneTransformer = {}));
34
+ //# sourceMappingURL=CloneTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloneTransformer.js","sourceRoot":"","sources":["../../../../src/transformers/features/miscellaneous/CloneTransformer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0DAA4B;AAE5B,wEAAuE;AAIvE,IAAiB,gBAAgB,CAkChC;AAlCD,WAAiB,gBAAgB;IAC7B,SAAgB,SAAS,CACrB,OAAiB,EACjB,MAAiC,EACjC,UAA6B;QAE7B,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;YACjC,MAAM,IAAI,KAAK,2CAA8B,CAAC;QAElD,IAAM,IAAI,GACN,UAAU,CAAC,aAAa,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;YACnD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAC/B,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAC9B;YACH,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,eAAe,EAAE;YACtB,MAAM,IAAI,KAAK,2DAAgC,CAAC;QAEpD,OAAO,oBAAE,CAAC,OAAO,CAAC,oBAAoB,CAClC,iCAAe,CAAC,QAAQ,uBAEb,OAAO,KACV,OAAO,wBACA,OAAO,CAAC,OAAO,KAClB,UAAU,EAAE,KAAK,EACjB,OAAO,EAAE,KAAK,QAGtB,MAAM,CACT,CAAC,IAAI,CAAC,EACP,SAAS,EACT,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,CAC7B,CAAC;IACN,CAAC;IAhCe,0BAAS,YAgCxB,CAAA;AACL,CAAC,EAlCgB,gBAAgB,GAAhB,wBAAgB,KAAhB,wBAAgB,QAkChC"}
@@ -0,0 +1,5 @@
1
+ import ts from "typescript";
2
+ import { IProject } from "../../IProject";
3
+ export declare namespace CreateCloneTransformer {
4
+ function transform(project: IProject, modulo: ts.LeftHandSideExpression, expression: ts.CallExpression): ts.Expression;
5
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateCloneTransformer = void 0;
4
+ var CloneProgrammer_1 = require("../../../programmers/CloneProgrammer");
5
+ var CreateCloneTransformer;
6
+ (function (CreateCloneTransformer) {
7
+ function transform(project, modulo, expression) {
8
+ if (!expression.typeArguments || !expression.typeArguments[0])
9
+ throw new Error("Error on typia.clone(): generic argument is not specified.");
10
+ var type = project.checker.getTypeFromTypeNode(expression.typeArguments[0]);
11
+ if (type.isTypeParameter())
12
+ throw new Error("Error on typia.clone(): non-specified generic argument.");
13
+ return CloneProgrammer_1.CloneProgrammer.generate(project, modulo)(type);
14
+ }
15
+ CreateCloneTransformer.transform = transform;
16
+ })(CreateCloneTransformer = exports.CreateCloneTransformer || (exports.CreateCloneTransformer = {}));
17
+ //# sourceMappingURL=CreateCloneTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateCloneTransformer.js","sourceRoot":"","sources":["../../../../src/transformers/features/miscellaneous/CreateCloneTransformer.ts"],"names":[],"mappings":";;;AAEA,wEAAuE;AAIvE,IAAiB,sBAAsB,CAmBtC;AAnBD,WAAiB,sBAAsB;IACnC,SAAgB,SAAS,CACrB,OAAiB,EACjB,MAAiC,EACjC,UAA6B;QAG7B,IAAI,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;YACzD,MAAM,IAAI,KAAK,8DAA6B,CAAC;QAGjD,IAAM,IAAI,GAAY,OAAO,CAAC,OAAO,CAAC,mBAAmB,CACrD,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAC9B,CAAC;QACF,IAAI,IAAI,CAAC,eAAe,EAAE;YACtB,MAAM,IAAI,KAAK,2DAAgC,CAAC;QAEpD,OAAO,iCAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IAjBe,gCAAS,YAiBxB,CAAA;AACL,CAAC,EAnBgB,sBAAsB,GAAtB,8BAAsB,KAAtB,8BAAsB,QAmBtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typia",
3
- "version": "3.5.0-dev.20230212",
3
+ "version": "3.5.0-dev.20230213",
4
4
  "description": "Superfast runtime validators with only one line",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
package/src/module.ts CHANGED
@@ -1105,6 +1105,28 @@ export function metadata(): never {
1105
1105
  halt("metadata");
1106
1106
  }
1107
1107
 
1108
+ export function clone<T>(input: T): T;
1109
+ export function clone(): never {
1110
+ halt("clone");
1111
+ }
1112
+ export namespace clone {
1113
+ export const is_uuid = $is_uuid;
1114
+ export const is_email = $is_email;
1115
+ export const is_url = $is_url;
1116
+ export const is_ipv4 = $is_ipv4;
1117
+ export const is_ipv6 = $is_ipv6;
1118
+ export const is_between = $is_between;
1119
+
1120
+ export function throws(
1121
+ props: Pick<TypeGuardError.IProps, "expected" | "value">,
1122
+ ): void {
1123
+ throw new TypeGuardError({
1124
+ ...props,
1125
+ method: "typia.clone",
1126
+ });
1127
+ }
1128
+ }
1129
+
1108
1130
  /**
1109
1131
  * Prune, erase superfluous properties.
1110
1132
  *
@@ -1764,6 +1786,17 @@ Object.assign(createValidateStringify, validateStringify);
1764
1786
  /* -----------------------------------------------------------
1765
1787
  MISCELLANEOUS
1766
1788
  ----------------------------------------------------------- */
1789
+ export function createClone(): never;
1790
+ export function createClone<T>(): (input: T) => T;
1791
+
1792
+ /**
1793
+ * @internal
1794
+ */
1795
+ export function createClone(): never {
1796
+ halt("createClone");
1797
+ }
1798
+ Object.assign(createClone, clone);
1799
+
1767
1800
  /**
1768
1801
  * Creates a reusable {@link prune} function.
1769
1802
  *
@@ -0,0 +1,357 @@
1
+ import ts from "typescript";
2
+
3
+ import { ExpressionFactory } from "../factories/ExpressionFactory";
4
+ import { IdentifierFactory } from "../factories/IdentifierFactory";
5
+ import { MetadataCollection } from "../factories/MetadataCollection";
6
+ import { MetadataFactory } from "../factories/MetadataFactory";
7
+
8
+ import { Metadata } from "../metadata/Metadata";
9
+
10
+ import { IProject } from "../transformers/IProject";
11
+
12
+ import { FeatureProgrammer } from "./FeatureProgrammer";
13
+ import { IsProgrammer } from "./IsProgrammer";
14
+ import { CloneJoiner } from "./helpers/CloneJoiner";
15
+ import { FunctionImporter } from "./helpers/FunctionImporeter";
16
+ import { UnionExplorer } from "./helpers/UnionExplorer";
17
+ import { decode_union_object } from "./internal/decode_union_object";
18
+
19
+ export namespace CloneProgrammer {
20
+ export function generate(
21
+ project: IProject,
22
+ modulo: ts.LeftHandSideExpression,
23
+ ) {
24
+ const importer: FunctionImporter = new FunctionImporter();
25
+ return FeatureProgrammer.generate(
26
+ project,
27
+ CONFIG(project, importer),
28
+ importer,
29
+ (collection) => {
30
+ const isFunctors = IsProgrammer.generate_functors(
31
+ project,
32
+ importer,
33
+ )(collection);
34
+ const isUnioners = IsProgrammer.generate_unioners(
35
+ project,
36
+ importer,
37
+ )(collection);
38
+
39
+ return [
40
+ ...importer.declare(modulo),
41
+ ...isFunctors,
42
+ ...isUnioners,
43
+ ];
44
+ },
45
+ );
46
+ }
47
+
48
+ /* -----------------------------------------------------------
49
+ DECODERS
50
+ ----------------------------------------------------------- */
51
+ const decode =
52
+ (project: IProject, importer: FunctionImporter) =>
53
+ (
54
+ input: ts.Expression,
55
+ meta: Metadata,
56
+ explore: FeatureProgrammer.IExplore,
57
+ ): ts.Expression => {
58
+ // ANY TYPE
59
+ if (
60
+ meta.any ||
61
+ meta.arrays.some((a) => a.any) ||
62
+ meta.tuples.some((t) => t.every((e) => e.any))
63
+ )
64
+ return ts.factory.createCallExpression(
65
+ ts.factory.createIdentifier("JSON.parse"),
66
+ undefined,
67
+ [
68
+ ts.factory.createCallExpression(
69
+ ts.factory.createIdentifier("JSON.stringify"),
70
+ undefined,
71
+ [input],
72
+ ),
73
+ ],
74
+ );
75
+
76
+ interface IUnion {
77
+ type: string;
78
+ is: () => ts.Expression;
79
+ value: () => ts.Expression;
80
+ }
81
+ const unions: IUnion[] = [];
82
+
83
+ //----
84
+ // LIST UP UNION TYPES
85
+ //----
86
+ // toJSON() METHOD
87
+ if (meta.resolved !== null)
88
+ unions.push({
89
+ type: "resolved",
90
+ is: () => IsProgrammer.decode_to_json(input),
91
+ value: () =>
92
+ decode_to_json(project, importer)(
93
+ input,
94
+ meta.resolved!,
95
+ explore,
96
+ ),
97
+ });
98
+
99
+ // TUPLES
100
+ for (const tuple of meta.tuples)
101
+ unions.push({
102
+ type: "tuple",
103
+ is: () =>
104
+ IsProgrammer.decode(project, importer)(
105
+ input,
106
+ (() => {
107
+ const partial = Metadata.initialize();
108
+ partial.tuples.push(tuple);
109
+ return partial;
110
+ })(),
111
+ explore,
112
+ [],
113
+ ),
114
+ value: () =>
115
+ decode_tuple(project, importer)(input, tuple, explore),
116
+ });
117
+
118
+ // ARRAYS
119
+ if (meta.arrays.length)
120
+ unions.push({
121
+ type: "array",
122
+ is: () => ExpressionFactory.isArray(input),
123
+ value: () =>
124
+ explore_arrays(project, importer)(
125
+ input,
126
+ meta.arrays,
127
+ {
128
+ ...explore,
129
+ from: "array",
130
+ },
131
+ [],
132
+ ),
133
+ });
134
+
135
+ // NATIVE TYPES
136
+ if (meta.sets.length)
137
+ unions.push({
138
+ type: "set",
139
+ is: () => ExpressionFactory.isInstanceOf(input, "Set"),
140
+ value: () => ts.factory.createIdentifier("{}"),
141
+ });
142
+ if (meta.maps.length)
143
+ unions.push({
144
+ type: "map",
145
+ is: () => ExpressionFactory.isInstanceOf(input, "Map"),
146
+ value: () => ts.factory.createIdentifier("{}"),
147
+ });
148
+ for (const native of meta.natives)
149
+ unions.push({
150
+ type: "native",
151
+ is: () => ExpressionFactory.isInstanceOf(input, native),
152
+ value: () => ts.factory.createIdentifier("{}"),
153
+ });
154
+
155
+ // OBJECTS
156
+ if (meta.objects.length)
157
+ unions.push({
158
+ type: "object",
159
+ is: () =>
160
+ ExpressionFactory.isObject(input, {
161
+ checkNull: true,
162
+ checkArray: false,
163
+ }),
164
+ value: () =>
165
+ explore_objects(input, meta, {
166
+ ...explore,
167
+ from: "object",
168
+ }),
169
+ });
170
+
171
+ // COMPOSITION
172
+ let last: ts.Expression = input;
173
+ for (const u of unions.reverse())
174
+ last = ts.factory.createConditionalExpression(
175
+ u.is(),
176
+ undefined,
177
+ u.value(),
178
+ undefined,
179
+ last,
180
+ );
181
+ return last;
182
+ };
183
+
184
+ const decode_to_json =
185
+ (project: IProject, importer: FunctionImporter) =>
186
+ (
187
+ input: ts.Expression,
188
+ resolved: Metadata,
189
+ explore: FeatureProgrammer.IExplore,
190
+ ): ts.Expression => {
191
+ return decode(project, importer)(
192
+ ts.factory.createCallExpression(
193
+ IdentifierFactory.join(input, "toJSON"),
194
+ undefined,
195
+ [],
196
+ ),
197
+ resolved,
198
+ explore,
199
+ );
200
+ };
201
+
202
+ const decode_tuple =
203
+ (project: IProject, importer: FunctionImporter) =>
204
+ (
205
+ input: ts.Expression,
206
+ tuple: Metadata[],
207
+ explore: FeatureProgrammer.IExplore,
208
+ ): ts.Expression => {
209
+ const children: ts.Expression[] = tuple
210
+ .filter((m) => m.rest === null)
211
+ .map((elem, index) =>
212
+ decode(project, importer)(
213
+ ts.factory.createElementAccessExpression(input, index),
214
+ elem,
215
+ {
216
+ ...explore,
217
+ from: "array",
218
+ },
219
+ ),
220
+ );
221
+ const rest = (() => {
222
+ if (tuple.length === 0) return null;
223
+
224
+ const last: Metadata = tuple[tuple.length - 1]!;
225
+ const rest: Metadata | null = last.rest;
226
+ if (rest === null) return null;
227
+
228
+ return decode(project, importer)(
229
+ ts.factory.createCallExpression(
230
+ IdentifierFactory.join(input, "slice"),
231
+ undefined,
232
+ [ts.factory.createNumericLiteral(tuple.length - 1)],
233
+ ),
234
+ (() => {
235
+ const wrapper: Metadata = Metadata.initialize();
236
+ wrapper.arrays.push(rest);
237
+ return wrapper;
238
+ })(),
239
+ {
240
+ ...explore,
241
+ start: tuple.length - 1,
242
+ },
243
+ );
244
+ })();
245
+ return CloneJoiner.tuple(children, rest);
246
+ };
247
+
248
+ const decode_array = (project: IProject, importer: FunctionImporter) =>
249
+ FeatureProgrammer.decode_array(
250
+ CONFIG(project, importer),
251
+ importer,
252
+ CloneJoiner.array,
253
+ );
254
+
255
+ const decode_object = () =>
256
+ FeatureProgrammer.decode_object({
257
+ trace: false,
258
+ path: false,
259
+ functors: FUNCTORS,
260
+ });
261
+
262
+ const explore_arrays = (project: IProject, importer: FunctionImporter) =>
263
+ UnionExplorer.array({
264
+ checker: IsProgrammer.decode(project, importer),
265
+ decoder: decode_array(project, importer),
266
+ empty: ts.factory.createReturnStatement(),
267
+ success: ts.factory.createTrue(),
268
+ failure: (input, expected) =>
269
+ create_throw_error(importer, input, expected),
270
+ });
271
+
272
+ const explore_objects = (
273
+ input: ts.Expression,
274
+ meta: Metadata,
275
+ explore: FeatureProgrammer.IExplore,
276
+ ) => {
277
+ if (meta.objects.length === 1)
278
+ return decode_object()(input, meta.objects[0]!, explore);
279
+
280
+ return ts.factory.createCallExpression(
281
+ ts.factory.createIdentifier(`${UNIONERS}${meta.union_index!}`),
282
+ undefined,
283
+ [input],
284
+ );
285
+ };
286
+
287
+ /* -----------------------------------------------------------
288
+ CONFIGURATIONS
289
+ ----------------------------------------------------------- */
290
+ const FUNCTORS = "$co";
291
+ const UNIONERS = "$cu";
292
+
293
+ const CONFIG = (
294
+ project: IProject,
295
+ importer: FunctionImporter,
296
+ ): FeatureProgrammer.IConfig => ({
297
+ functors: FUNCTORS,
298
+ unioners: UNIONERS,
299
+ trace: false,
300
+ path: false,
301
+ initializer,
302
+ decoder: decode(project, importer),
303
+ objector: OBJECTOR(project, importer),
304
+ });
305
+
306
+ const OBJECTOR = (
307
+ project: IProject,
308
+ importer: FunctionImporter,
309
+ ): FeatureProgrammer.IConfig.IObjector => ({
310
+ checker: IsProgrammer.decode(project, importer),
311
+ decoder: decode_object(),
312
+ joiner: CloneJoiner.object,
313
+ unionizer: decode_union_object(IsProgrammer.decode_object(importer))(
314
+ decode_object(),
315
+ )((exp) => exp)((value, expected) =>
316
+ create_throw_error(importer, value, expected),
317
+ ),
318
+ failure: (input, expected) =>
319
+ create_throw_error(importer, input, expected),
320
+ });
321
+
322
+ const initializer: FeatureProgrammer.IConfig["initializer"] = (
323
+ { checker },
324
+ type,
325
+ ) => {
326
+ const collection = new MetadataCollection();
327
+ const meta = MetadataFactory.generate(checker, collection, type, {
328
+ resolve: true,
329
+ constant: true,
330
+ });
331
+ return [collection, meta];
332
+ };
333
+
334
+ const create_throw_error = (
335
+ importer: FunctionImporter,
336
+ value: ts.Expression,
337
+ expected: string,
338
+ ) =>
339
+ ts.factory.createExpressionStatement(
340
+ ts.factory.createCallExpression(
341
+ importer.use("throws"),
342
+ [],
343
+ [
344
+ ts.factory.createObjectLiteralExpression(
345
+ [
346
+ ts.factory.createPropertyAssignment(
347
+ "expected",
348
+ ts.factory.createStringLiteral(expected),
349
+ ),
350
+ ts.factory.createPropertyAssignment("value", value),
351
+ ],
352
+ true,
353
+ ),
354
+ ],
355
+ ),
356
+ );
357
+ }
@@ -0,0 +1,126 @@
1
+ import ts from "typescript";
2
+
3
+ import { StatementFactory } from "../../factories/StatementFactory";
4
+
5
+ import { MetadataObject } from "../../metadata/MetadataObject";
6
+
7
+ import { Escaper } from "../../utils/Escaper";
8
+
9
+ import { metadata_to_pattern } from "../internal/metadata_to_pattern";
10
+ import { IExpressionEntry } from "./IExpressionEntry";
11
+
12
+ export namespace CloneJoiner {
13
+ export const object = (
14
+ input: ts.Expression,
15
+ entries: IExpressionEntry<ts.Expression>[],
16
+ _obj: MetadataObject,
17
+ ): ts.ConciseBody => {
18
+ const regular = entries.filter((e) => e.key.isSoleLiteral());
19
+ const dynamic = entries.filter((e) => !e.key.isSoleLiteral());
20
+
21
+ if (regular.length === 0 && dynamic.length === 0)
22
+ return ts.factory.createIdentifier("{}");
23
+
24
+ const literal = ts.factory.createObjectLiteralExpression(
25
+ regular.map((entry) => {
26
+ const str: string = entry.key.getSoleLiteral()!;
27
+ return ts.factory.createPropertyAssignment(
28
+ Escaper.variable(str)
29
+ ? str
30
+ : ts.factory.createStringLiteral(str),
31
+ entry.expression,
32
+ );
33
+ }),
34
+ true,
35
+ );
36
+ if (dynamic.length === 0) return literal;
37
+
38
+ const key = ts.factory.createIdentifier("key");
39
+ const value = ts.factory.createIdentifier("value");
40
+ const output = ts.factory.createIdentifier("output");
41
+
42
+ const statements: ts.Statement[] = dynamic.map((entry) =>
43
+ ts.factory.createIfStatement(
44
+ ts.factory.createCallExpression(
45
+ ts.factory.createIdentifier(
46
+ `RegExp(/${metadata_to_pattern(true)(
47
+ entry.key,
48
+ )}/).test`,
49
+ ),
50
+ undefined,
51
+ [key],
52
+ ),
53
+ ts.factory.createBlock([
54
+ ts.factory.createExpressionStatement(
55
+ ts.factory.createBinaryExpression(
56
+ ts.factory.createElementAccessExpression(
57
+ output,
58
+ key,
59
+ ),
60
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
61
+ entry.expression,
62
+ ),
63
+ ),
64
+ ts.factory.createContinueStatement(),
65
+ ]),
66
+ ),
67
+ );
68
+
69
+ return ts.factory.createBlock([
70
+ StatementFactory.constant("output", literal),
71
+ ts.factory.createForOfStatement(
72
+ undefined,
73
+ ts.factory.createVariableDeclarationList(
74
+ [
75
+ ts.factory.createVariableDeclaration(
76
+ ts.factory.createArrayBindingPattern([
77
+ ts.factory.createBindingElement(
78
+ undefined,
79
+ undefined,
80
+ key,
81
+ undefined,
82
+ ),
83
+ ts.factory.createBindingElement(
84
+ undefined,
85
+ undefined,
86
+ value,
87
+ undefined,
88
+ ),
89
+ ]),
90
+ undefined,
91
+ undefined,
92
+ undefined,
93
+ ),
94
+ ],
95
+ ts.NodeFlags.Const,
96
+ ),
97
+ ts.factory.createCallExpression(
98
+ ts.factory.createIdentifier("Object.entries"),
99
+ undefined,
100
+ [input],
101
+ ),
102
+ ts.factory.createBlock(statements),
103
+ ),
104
+ ts.factory.createReturnStatement(output),
105
+ ]);
106
+ };
107
+
108
+ export const tuple = (
109
+ children: ts.Expression[],
110
+ rest: ts.Expression | null,
111
+ ): ts.Expression => {
112
+ if (rest === null)
113
+ return ts.factory.createArrayLiteralExpression(children, true);
114
+ return ts.factory.createArrayLiteralExpression(
115
+ [...children, ts.factory.createSpreadElement(rest)],
116
+ true,
117
+ );
118
+ };
119
+
120
+ export const array = (input: ts.Expression, arrow: ts.Expression) =>
121
+ ts.factory.createCallExpression(
122
+ ts.factory.createPropertyAccessExpression(input, "map"),
123
+ undefined,
124
+ [arrow],
125
+ );
126
+ }
@@ -4,7 +4,9 @@ import ts from "typescript";
4
4
  import { IProject } from "./IProject";
5
5
  import { ApplicationTransformer } from "./features/miscellaneous/ApplicationTransformer";
6
6
  import { AssertPruneTransformer } from "./features/miscellaneous/AssertPruneTransformer";
7
+ import { CloneTransformer } from "./features/miscellaneous/CloneTransformer";
7
8
  import { CreateAssertPruneTransformer } from "./features/miscellaneous/CreateAssertPruneTransformer";
9
+ import { CreateCloneTransformer } from "./features/miscellaneous/CreateCloneTransformer";
8
10
  import { CreateIsPruneTransformer } from "./features/miscellaneous/CreateIsPruneTransformer";
9
11
  import { CreatePruneTransformer } from "./features/miscellaneous/CreatePruneTransformer";
10
12
  import { CreateValidatePruneTransformer } from "./features/miscellaneous/CreateValidatePruneTransformer";
@@ -96,14 +98,15 @@ const FUNCTORS: Record<string, () => Task> = {
96
98
  validateParse: () => ValidateParseTransformer.transform,
97
99
 
98
100
  // STRINGIFY FUNCTIONS
101
+ application: () => ApplicationTransformer.transform,
99
102
  stringify: () => StringifyTransformer.transform,
100
103
  assertStringify: () => AssertStringifyTransformer.transform,
101
104
  isStringify: () => IsStringifyTransformer.transform,
102
105
  validateStringify: () => ValidateStringifyTransformer.transform,
103
106
 
104
107
  // MISC
105
- application: () => ApplicationTransformer.transform,
106
108
  metadata: () => MetadataTransformer.transform,
109
+ clone: () => CloneTransformer.transform,
107
110
  prune: () => PruneTransformer.transform,
108
111
  assertPrune: () => AssertPruneTransformer.transform,
109
112
  isPrune: () => IsPruneTransformer.transform,
@@ -135,6 +138,7 @@ const FUNCTORS: Record<string, () => Task> = {
135
138
  createValidateStringify: () => CreateValidateStringifyTransformer.transform,
136
139
 
137
140
  // MISC
141
+ createClone: () => CreateCloneTransformer.transform,
138
142
  createPrune: () => CreatePruneTransformer.transform,
139
143
  createAssertPrune: () => CreateAssertPruneTransformer.transform,
140
144
  createIsPrune: () => CreateIsPruneTransformer.transform,
@@ -0,0 +1,46 @@
1
+ import ts from "typescript";
2
+
3
+ import { CloneProgrammer } from "../../../programmers/CloneProgrammer";
4
+
5
+ import { IProject } from "../../IProject";
6
+
7
+ export namespace CloneTransformer {
8
+ export function transform(
9
+ project: IProject,
10
+ modulo: ts.LeftHandSideExpression,
11
+ expression: ts.CallExpression,
12
+ ): ts.Expression {
13
+ if (expression.arguments.length !== 1)
14
+ throw new Error(ErrorMessages.NO_INPUT_VALUE);
15
+
16
+ const type: ts.Type =
17
+ expression.typeArguments && expression.typeArguments[0]
18
+ ? project.checker.getTypeFromTypeNode(
19
+ expression.typeArguments[0],
20
+ )
21
+ : project.checker.getTypeAtLocation(expression.arguments[0]!);
22
+ if (type.isTypeParameter())
23
+ throw new Error(ErrorMessages.GENERIC_ARGUMENT);
24
+
25
+ return ts.factory.createCallExpression(
26
+ CloneProgrammer.generate(
27
+ {
28
+ ...project,
29
+ options: {
30
+ ...project.options,
31
+ functional: false,
32
+ numeric: false,
33
+ },
34
+ },
35
+ modulo,
36
+ )(type),
37
+ undefined,
38
+ [expression.arguments[0]!],
39
+ );
40
+ }
41
+ }
42
+
43
+ const enum ErrorMessages {
44
+ NO_INPUT_VALUE = "Error on typia.clone(): no input value.",
45
+ GENERIC_ARGUMENT = "Error on typia.clone(): non-specified generic argument.",
46
+ }