typia 3.4.18 → 3.4.19

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.
Files changed (36) hide show
  1. package/lib/metadata/Metadata.js +32 -29
  2. package/lib/metadata/Metadata.js.map +1 -1
  3. package/lib/programmers/AssertProgrammer.js +1 -1
  4. package/lib/programmers/AssertProgrammer.js.map +1 -1
  5. package/lib/programmers/CheckerProgrammer.d.ts +1 -0
  6. package/lib/programmers/CheckerProgrammer.js +147 -138
  7. package/lib/programmers/CheckerProgrammer.js.map +1 -1
  8. package/lib/programmers/ValidateProgrammer.js +1 -1
  9. package/lib/programmers/ValidateProgrammer.js.map +1 -1
  10. package/lib/programmers/helpers/UnionExplorer.d.ts +23 -29
  11. package/lib/programmers/helpers/UnionExplorer.js +29 -41
  12. package/lib/programmers/helpers/UnionExplorer.js.map +1 -1
  13. package/lib/programmers/internal/check_array.js +4 -32
  14. package/lib/programmers/internal/check_array.js.map +1 -1
  15. package/lib/programmers/internal/check_array_length.d.ts +1 -0
  16. package/lib/programmers/internal/check_array_length.js +47 -0
  17. package/lib/programmers/internal/check_array_length.js.map +1 -0
  18. package/lib/programmers/internal/check_union_array_like.d.ts +21 -0
  19. package/lib/programmers/internal/check_union_array_like.js +83 -0
  20. package/lib/programmers/internal/check_union_array_like.js.map +1 -0
  21. package/lib/programmers/internal/check_union_tuple.d.ts +1 -0
  22. package/lib/programmers/internal/check_union_tuple.js +11 -0
  23. package/lib/programmers/internal/check_union_tuple.js.map +1 -0
  24. package/package.json +1 -1
  25. package/src/executable/typia.ts +48 -48
  26. package/src/functional/$guard.ts +35 -35
  27. package/src/metadata/Metadata.ts +10 -7
  28. package/src/programmers/AssertProgrammer.ts +1 -1
  29. package/src/programmers/CheckerProgrammer.ts +252 -200
  30. package/src/programmers/FeatureProgrammer.ts +327 -327
  31. package/src/programmers/ValidateProgrammer.ts +1 -1
  32. package/src/programmers/helpers/UnionExplorer.ts +75 -238
  33. package/src/programmers/internal/check_array.ts +3 -25
  34. package/src/programmers/internal/check_array_length.ts +45 -0
  35. package/src/programmers/internal/check_union_array_like.ts +242 -0
  36. package/src/programmers/internal/check_union_tuple.ts +33 -0
@@ -18,11 +18,13 @@ import { IExpressionEntry } from "./helpers/IExpressionEntry";
18
18
  import { OptionPredicator } from "./helpers/OptionPredicator";
19
19
  import { UnionExplorer } from "./helpers/UnionExplorer";
20
20
  import { check_array } from "./internal/check_array";
21
+ import { check_array_length } from "./internal/check_array_length";
21
22
  import { check_bigint } from "./internal/check_bigint";
22
23
  import { check_native } from "./internal/check_native";
23
24
  import { check_number } from "./internal/check_number";
24
25
  import { check_string } from "./internal/check_string";
25
26
  import { check_template } from "./internal/check_template";
27
+ import { check_union_tuple } from "./internal/check_union_tuple";
26
28
  import { decode_union_object } from "./internal/decode_union_object";
27
29
 
28
30
  export namespace CheckerProgrammer {
@@ -222,7 +224,6 @@ export namespace CheckerProgrammer {
222
224
  project: IProject,
223
225
  config: IConfig,
224
226
  importer: FunctionImporter,
225
- checkTupleLength: boolean = true,
226
227
  ) {
227
228
  return function (
228
229
  input: ts.Expression,
@@ -328,212 +329,199 @@ export namespace CheckerProgrammer {
328
329
  combined: false,
329
330
  });
330
331
 
332
+ // NATIVE CLASSES
333
+ for (const native of meta.natives)
334
+ binaries.push({
335
+ expression: check_native(native)(input),
336
+ combined: false,
337
+ });
338
+
331
339
  //----
332
340
  // INSTANCES
333
341
  //----
334
- // TUPLE
335
- if (meta.tuples.length > 0) {
336
- const inner: ts.Expression[] = [];
337
- for (const tuple of meta.tuples)
338
- inner.push(
339
- decode_tuple(
340
- project,
341
- config,
342
- importer,
343
- checkTupleLength,
344
- )(input, tuple, explore, tags),
345
- );
342
+ interface IInstance {
343
+ pre: ts.Expression;
344
+ body: ts.Expression | null;
345
+ expected: string;
346
+ }
347
+ const instances: IInstance[] = [];
348
+ const prepare =
349
+ (pre: ts.Expression, expected: string) =>
350
+ (body: ts.Expression | null) =>
351
+ instances.push({
352
+ pre,
353
+ expected,
354
+ body,
355
+ });
346
356
 
347
- // ADD
348
- binaries.push({
349
- expression: config.combiner(explore)("and")(
350
- input,
351
- [
352
- ...(checkTupleLength
353
- ? [
354
- {
355
- expression:
356
- ExpressionFactory.isArray(input),
357
- combined: false,
358
- },
359
- ]
360
- : []),
361
- ...inner.map((expression) => ({
362
- expression,
363
- combined: true,
364
- })),
365
- ],
366
- meta.getName(),
367
- ),
368
- combined: true,
369
- });
357
+ // SETS
358
+ if (meta.sets.length) {
359
+ const install = prepare(
360
+ check_native("Set")(input),
361
+ meta.sets
362
+ .map((elem) => `Set<${elem.getName()}>`)
363
+ .join(" | "),
364
+ );
365
+ if (meta.sets.some((elem) => elem.any)) install(null);
366
+ else
367
+ install(
368
+ explore_sets(project, config, importer)(
369
+ input,
370
+ meta.sets,
371
+ {
372
+ ...explore,
373
+ from: "array",
374
+ },
375
+ [],
376
+ ),
377
+ );
370
378
  }
371
379
 
372
- // ARRAY
373
- if (meta.arrays.length > 0)
374
- if (meta.arrays.every((elem) => elem.any))
375
- binaries.push({
376
- expression: check_array(input, tags),
377
- combined: false,
378
- });
380
+ // MAPS
381
+ if (meta.maps.length) {
382
+ const install = prepare(
383
+ check_native("Map")(input),
384
+ meta.maps
385
+ .map(({ key, value }) => `Map<${key}, ${value}>`)
386
+ .join(" | "),
387
+ );
388
+ if (meta.maps.some((elem) => elem.key.any && elem.value.any))
389
+ install(null);
379
390
  else
380
- binaries.push({
381
- expression: config.combiner(explore)("and")(
391
+ install(
392
+ explore_maps(project, config, importer)(
382
393
  input,
383
- [
384
- ...(checkTupleLength
385
- ? [
386
- {
387
- expression: check_array(
388
- input,
389
- tags,
390
- ),
391
- combined: false,
392
- },
393
- ]
394
- : []),
395
- {
396
- expression: explore_array(
397
- project,
398
- config,
399
- importer,
400
- )(
401
- input,
402
- meta.arrays,
403
- {
404
- ...explore,
405
- from: "array",
406
- },
407
- tags,
408
- ),
409
- combined: true,
410
- },
411
- ],
412
- meta.getName(),
394
+ meta.maps.map((m) => [m.key, m.value]),
395
+ {
396
+ ...explore,
397
+ from: "array",
398
+ },
399
+ [],
413
400
  ),
414
- combined: true,
415
- });
401
+ );
402
+ }
416
403
 
417
- // OBJECT
418
- if (meta.objects.length > 0)
419
- binaries.push({
420
- expression: config.combiner(explore)("and")(
421
- input,
422
- [
404
+ // ARRAYS AND TUPLES
405
+ if (meta.tuples.length + meta.arrays.length > 0) {
406
+ const install = prepare(
407
+ check_array(input, meta.tuples.length === 0 ? tags : []),
408
+ [...meta.tuples, ...meta.arrays]
409
+ .map((elem) =>
410
+ Array.isArray(elem)
411
+ ? `[${elem
412
+ .map((elem) => elem.getName())
413
+ .join(", ")}]`
414
+ : `Array<${elem.getName()}>`,
415
+ )
416
+ .join(" | "),
417
+ );
418
+ if (meta.arrays.length === 0)
419
+ install(
420
+ explore_tuples(project, config, importer)(
421
+ input,
422
+ meta.tuples,
423
423
  {
424
- expression: ExpressionFactory.isObject(input, {
425
- checkNull: true,
426
- checkArray: meta.objects.some((obj) =>
427
- obj.properties.every(
428
- (prop) =>
429
- !prop.key.isSoleLiteral() ||
430
- !prop.value.required,
431
- ),
432
- ),
433
- }),
434
- combined: false,
424
+ ...explore,
425
+ from: "array",
435
426
  },
427
+ tags,
428
+ ),
429
+ );
430
+ else if (meta.arrays.some((elem) => elem.any)) install(null);
431
+ else if (meta.tuples.length === 0)
432
+ // ARRAY ONLY
433
+ install(
434
+ explore_arrays(project, config, importer)(
435
+ input,
436
+ meta.arrays,
436
437
  {
437
- expression: explore_objects(config)(
438
- input,
439
- meta,
440
- {
441
- ...explore,
442
- from: "object",
443
- },
444
- ),
445
- combined: true,
438
+ ...explore,
439
+ from: "array",
446
440
  },
447
- ],
448
- meta.getName(),
449
- ),
450
- combined: true,
451
- });
452
-
453
- // NATIVE CLASSES
454
- for (const native of meta.natives)
455
- binaries.push({
456
- expression: check_native(native)(input),
457
- combined: false,
458
- });
459
-
460
- // SETS
461
- if (meta.sets.length)
462
- if (meta.sets.every((elem) => elem.any))
463
- binaries.push({
464
- combined: false,
465
- expression: check_native("Set")(input),
466
- });
441
+ tags,
442
+ ),
443
+ );
467
444
  else
468
- binaries.push({
469
- combined: true,
470
- expression: config.combiner(explore)("and")(
445
+ install(
446
+ explore_arrays_and_tuples(project, config, importer)(
471
447
  input,
472
- [
473
- {
474
- combined: false,
475
- expression: check_native("Set")(input),
476
- },
477
- {
478
- combined: true,
479
- expression: explore_set(
480
- project,
481
- config,
482
- importer,
483
- )(
484
- input,
485
- meta.sets,
486
- {
487
- ...explore,
488
- from: "array",
489
- },
490
- [],
491
- ),
492
- },
493
- ],
494
- meta.getName(),
448
+ [...meta.tuples, ...meta.arrays],
449
+ explore,
450
+ tags,
495
451
  ),
496
- });
452
+ );
453
+ }
497
454
 
498
- // MAPS
499
- if (meta.maps.length)
500
- if (meta.maps.every((elem) => elem.key.any && elem.value.any))
501
- binaries.push({
502
- expression: check_native("Map")(input),
503
- combined: false,
504
- });
455
+ // OBJECT
456
+ if (meta.objects.length > 0)
457
+ prepare(
458
+ ExpressionFactory.isObject(input, {
459
+ checkNull: true,
460
+ checkArray: meta.objects.some((obj) =>
461
+ obj.properties.every(
462
+ (prop) =>
463
+ !prop.key.isSoleLiteral() ||
464
+ !prop.value.required,
465
+ ),
466
+ ),
467
+ }),
468
+ meta.objects
469
+ .map((obj) => `Resolve<${obj.name}>`)
470
+ .join(" | "),
471
+ )(
472
+ explore_objects(config)(input, meta, {
473
+ ...explore,
474
+ from: "object",
475
+ }),
476
+ );
477
+
478
+ if (instances.length) {
479
+ const transformer =
480
+ (
481
+ merger: (
482
+ x: ts.Expression,
483
+ y: ts.Expression,
484
+ ) => ts.Expression,
485
+ ) =>
486
+ (ins: IInstance) =>
487
+ ins.body
488
+ ? {
489
+ expression: merger(ins.pre, ins.body),
490
+ combined: true,
491
+ }
492
+ : {
493
+ expression: ins.pre,
494
+ combined: false,
495
+ };
496
+ if (instances.length === 1)
497
+ binaries.push(
498
+ transformer((pre, body) =>
499
+ config.combiner(explore)("and")(
500
+ input,
501
+ [pre, body].map((expression) => ({
502
+ expression,
503
+ combined: expression !== pre,
504
+ })),
505
+ meta.getName(),
506
+ ),
507
+ )(instances[0]!),
508
+ );
505
509
  else
506
510
  binaries.push({
507
- combined: true,
508
- expression: config.combiner(explore)("and")(
511
+ expression: config.combiner(explore)("or")(
509
512
  input,
510
- [
511
- {
512
- combined: false,
513
- expression: check_native("Map")(input),
514
- },
515
- {
516
- combined: true,
517
- expression: explore_map(
518
- project,
519
- config,
520
- importer,
521
- )(
522
- input,
523
- meta.maps.map((m) => [m.key, m.value]),
524
- {
525
- ...explore,
526
- from: "array",
527
- },
528
- [],
529
- ),
530
- },
531
- ],
513
+ instances.map(
514
+ transformer(ts.factory.createLogicalAnd),
515
+ ),
532
516
  meta.getName(),
533
517
  ),
518
+ combined: true,
534
519
  });
520
+ }
535
521
 
522
+ //----
536
523
  // COMBINE CONDITIONS
524
+ //----
537
525
  return top.length && binaries.length
538
526
  ? config.combiner(explore)("and")(
539
527
  input,
@@ -560,7 +548,7 @@ export namespace CheckerProgrammer {
560
548
  };
561
549
  }
562
550
 
563
- function decode_tuple(
551
+ export function decode_tuple(
564
552
  project: IProject,
565
553
  config: IConfig,
566
554
  importer: FunctionImporter,
@@ -688,23 +676,7 @@ export namespace CheckerProgrammer {
688
676
  };
689
677
  }
690
678
 
691
- const explore_array = (
692
- project: IProject,
693
- config: IConfig,
694
- importer: FunctionImporter,
695
- ) =>
696
- UnionExplorer.array({
697
- checker: decode(project, config, importer),
698
- decoder: decode_array(project, config, importer, true),
699
- empty: config.success,
700
- success: config.success,
701
- failure: (input, expected, explore) =>
702
- ts.factory.createReturnStatement(
703
- config.joiner.failure(input, expected, explore),
704
- ),
705
- });
706
-
707
- const explore_set = (
679
+ const explore_sets = (
708
680
  project: IProject,
709
681
  config: IConfig,
710
682
  importer: FunctionImporter,
@@ -720,7 +692,7 @@ export namespace CheckerProgrammer {
720
692
  ),
721
693
  });
722
694
 
723
- const explore_map = (
695
+ const explore_maps = (
724
696
  project: IProject,
725
697
  config: IConfig,
726
698
  importer: FunctionImporter,
@@ -774,6 +746,86 @@ export namespace CheckerProgrammer {
774
746
  ),
775
747
  });
776
748
 
749
+ const explore_tuples = (
750
+ project: IProject,
751
+ config: IConfig,
752
+ importer: FunctionImporter,
753
+ ) =>
754
+ UnionExplorer.tuple({
755
+ checker: check_union_tuple(project, config, importer),
756
+ decoder: decode_tuple(project, config, importer, true),
757
+ empty: config.success,
758
+ success: config.success,
759
+ failure: (input, expected, explore) =>
760
+ ts.factory.createReturnStatement(
761
+ config.joiner.failure(input, expected, explore),
762
+ ),
763
+ });
764
+
765
+ const explore_arrays = (
766
+ project: IProject,
767
+ config: IConfig,
768
+ importer: FunctionImporter,
769
+ ) =>
770
+ UnionExplorer.array({
771
+ checker: decode(project, config, importer),
772
+ decoder: decode_array(project, config, importer, true),
773
+ empty: config.success,
774
+ success: config.success,
775
+ failure: (input, expected, explore) =>
776
+ ts.factory.createReturnStatement(
777
+ config.joiner.failure(input, expected, explore),
778
+ ),
779
+ });
780
+
781
+ const explore_arrays_and_tuples = (
782
+ project: IProject,
783
+ config: IConfig,
784
+ importer: FunctionImporter,
785
+ ) =>
786
+ UnionExplorer.array_or_tuple({
787
+ checker: (front, target, explore, tags, array) => {
788
+ if (Array.isArray(target))
789
+ return check_union_tuple(project, config, importer)(
790
+ front,
791
+ target,
792
+ explore,
793
+ tags,
794
+ array,
795
+ );
796
+ const condition = decode(project, config, importer)(
797
+ front,
798
+ target,
799
+ explore,
800
+ tags,
801
+ );
802
+ const length = check_array_length(array, tags);
803
+ return length !== null
804
+ ? ts.factory.createBitwiseAnd(condition, length)
805
+ : condition;
806
+ },
807
+ decoder: (input, target, explore, tags) =>
808
+ Array.isArray(target)
809
+ ? decode_tuple(project, config, importer, true)(
810
+ input,
811
+ target,
812
+ explore,
813
+ tags,
814
+ )
815
+ : decode_array(project, config, importer, true)(
816
+ input,
817
+ target,
818
+ explore,
819
+ tags,
820
+ ),
821
+ empty: config.success,
822
+ success: config.success,
823
+ failure: (input, expected, explore) =>
824
+ ts.factory.createReturnStatement(
825
+ config.joiner.failure(input, expected, explore),
826
+ ),
827
+ });
828
+
777
829
  const explore_objects = (config: IConfig) => {
778
830
  const objector = decode_object(config);
779
831