typia 3.4.24 → 3.4.25

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 (34) hide show
  1. package/lib/functional/$is_between.d.ts +1 -0
  2. package/lib/functional/$is_between.js +8 -0
  3. package/lib/functional/$is_between.js.map +1 -0
  4. package/lib/module.js +10 -0
  5. package/lib/module.js.map +1 -1
  6. package/lib/programmers/AssertProgrammer.js +79 -70
  7. package/lib/programmers/AssertProgrammer.js.map +1 -1
  8. package/lib/programmers/IsProgrammer.d.ts +3 -2
  9. package/lib/programmers/IsProgrammer.js +56 -46
  10. package/lib/programmers/IsProgrammer.js.map +1 -1
  11. package/lib/programmers/StringifyProgrammer.js +1 -1
  12. package/lib/programmers/StringifyProgrammer.js.map +1 -1
  13. package/lib/programmers/ValidateProgrammer.js +68 -59
  14. package/lib/programmers/ValidateProgrammer.js.map +1 -1
  15. package/lib/programmers/helpers/OptionPredicator.d.ts +1 -0
  16. package/lib/programmers/helpers/OptionPredicator.js +4 -0
  17. package/lib/programmers/helpers/OptionPredicator.js.map +1 -1
  18. package/lib/programmers/internal/check_dynamic_properties.js +32 -13
  19. package/lib/programmers/internal/check_dynamic_properties.js.map +1 -1
  20. package/lib/programmers/internal/check_object.d.ts +1 -0
  21. package/lib/programmers/internal/check_object.js +13 -9
  22. package/lib/programmers/internal/check_object.js.map +1 -1
  23. package/lib/transformers/ITransformOptions.d.ts +10 -0
  24. package/package.json +1 -1
  25. package/src/functional/$is_between.ts +7 -0
  26. package/src/module.ts +10 -0
  27. package/src/programmers/AssertProgrammer.ts +37 -30
  28. package/src/programmers/IsProgrammer.ts +72 -57
  29. package/src/programmers/StringifyProgrammer.ts +1 -1
  30. package/src/programmers/ValidateProgrammer.ts +37 -30
  31. package/src/programmers/helpers/OptionPredicator.ts +4 -0
  32. package/src/programmers/internal/check_dynamic_properties.ts +48 -21
  33. package/src/programmers/internal/check_object.ts +6 -2
  34. package/src/transformers/ITransformOptions.ts +11 -0
@@ -4,6 +4,7 @@ import { IdentifierFactory } from "../factories/IdentifierFactory";
4
4
 
5
5
  // import { StatementFactory } from "../factories/StatementFactory";
6
6
  import { IProject } from "../transformers/IProject";
7
+ import { ITransformOptions } from "../transformers/ITransformOptions";
7
8
 
8
9
  import { CheckerProgrammer } from "./CheckerProgrammer";
9
10
  import { IsProgrammer } from "./IsProgrammer";
@@ -240,8 +241,8 @@ export namespace AssertProgrammer {
240
241
  trace: true,
241
242
  numeric: OptionPredicator.numeric(project.options),
242
243
  equals,
243
- combiner: combiner(equals)(importer),
244
- joiner: joiner(equals)(importer),
244
+ combiner: combiner(project.options)(equals)(importer),
245
+ joiner: joiner(project.options)(equals)(importer),
245
246
  success: ts.factory.createTrue(),
246
247
  },
247
248
  importer,
@@ -277,14 +278,15 @@ export namespace AssertProgrammer {
277
278
  };
278
279
 
279
280
  const combiner =
281
+ (options: ITransformOptions) =>
280
282
  (equals: boolean) =>
281
283
  (importer: FunctionImporter): CheckerProgrammer.IConfig.Combiner =>
282
284
  (explore: CheckerProgrammer.IExplore) => {
283
285
  if (explore.tracable === false)
284
286
  return IsProgrammer.CONFIG({
285
- object: assert_object(equals)(importer),
287
+ object: assert_object(options)(equals)(importer),
286
288
  numeric: true,
287
- }).combiner(explore);
289
+ })(importer).combiner(explore);
288
290
 
289
291
  const path: string = explore.postfix
290
292
  ? `path + ${explore.postfix}`
@@ -350,39 +352,44 @@ export namespace AssertProgrammer {
350
352
  // );
351
353
  };
352
354
 
353
- const assert_object = (equals: boolean) => (importer: FunctionImporter) =>
354
- check_object({
355
- equals,
356
- assert: true,
357
- reduce: ts.factory.createLogicalAnd,
358
- positive: ts.factory.createTrue(),
359
- superfluous: (value) =>
360
- create_guard_call(importer)()(
361
- ts.factory.createAdd(
362
- ts.factory.createIdentifier("path"),
363
- ts.factory.createCallExpression(
364
- importer.use("join"),
365
- undefined,
366
- [ts.factory.createIdentifier("key")],
355
+ const assert_object =
356
+ (options: ITransformOptions) =>
357
+ (equals: boolean) =>
358
+ (importer: FunctionImporter) =>
359
+ check_object({
360
+ equals,
361
+ assert: true,
362
+ undefined: OptionPredicator.undefined(options),
363
+ reduce: ts.factory.createLogicalAnd,
364
+ positive: ts.factory.createTrue(),
365
+ superfluous: (value) =>
366
+ create_guard_call(importer)()(
367
+ ts.factory.createAdd(
368
+ ts.factory.createIdentifier("path"),
369
+ ts.factory.createCallExpression(
370
+ importer.use("join"),
371
+ undefined,
372
+ [ts.factory.createIdentifier("key")],
373
+ ),
367
374
  ),
375
+ "undefined",
376
+ value,
368
377
  ),
369
- "undefined",
370
- value,
371
- ),
372
- halt: (expr) =>
373
- ts.factory.createLogicalOr(
374
- ts.factory.createStrictEquality(
375
- ts.factory.createFalse(),
376
- ts.factory.createIdentifier("exceptionable"),
378
+ halt: (expr) =>
379
+ ts.factory.createLogicalOr(
380
+ ts.factory.createStrictEquality(
381
+ ts.factory.createFalse(),
382
+ ts.factory.createIdentifier("exceptionable"),
383
+ ),
384
+ expr,
377
385
  ),
378
- expr,
379
- ),
380
- });
386
+ })(importer);
381
387
 
382
388
  const joiner =
389
+ (options: ITransformOptions) =>
383
390
  (equals: boolean) =>
384
391
  (importer: FunctionImporter): CheckerProgrammer.IConfig.IJoiner => ({
385
- object: assert_object(equals)(importer),
392
+ object: assert_object(options)(equals)(importer),
386
393
  array: (input, arrow) =>
387
394
  ts.factory.createCallExpression(
388
395
  IdentifierFactory.join(input, "every"),
@@ -16,60 +16,64 @@ import { check_object } from "./internal/check_object";
16
16
  import { feature_object_entries } from "./internal/feature_object_entries";
17
17
 
18
18
  export namespace IsProgrammer {
19
- export const CONFIG = (
20
- options?: Partial<CONFIG.IOptions>,
21
- ): CheckerProgrammer.IConfig => ({
22
- functors: "$io",
23
- unioners: "$iu",
24
- trace: false,
25
- path: false,
26
- equals: !!options?.object,
27
- numeric: OptionPredicator.numeric({
28
- numeric: options?.numeric,
29
- }),
30
- combiner: () => (type: "and" | "or") => {
31
- const initial: ts.TrueLiteral | ts.FalseLiteral =
32
- type === "and"
33
- ? ts.factory.createTrue()
34
- : ts.factory.createFalse();
35
- const binder =
36
- type === "and"
37
- ? ts.factory.createLogicalAnd
38
- : ts.factory.createLogicalOr;
39
- return (
40
- _input: ts.Expression,
41
- binaries: CheckerProgrammer.IBinary[],
42
- ) =>
43
- binaries.length
44
- ? binaries
45
- .map((binary) => binary.expression)
46
- .reduce((x, y) => binder(x, y))
47
- : initial;
48
- },
49
- joiner: {
50
- object:
51
- options?.object ||
52
- check_object({
53
- equals: !!options?.object,
54
- assert: true,
55
- reduce: ts.factory.createLogicalAnd,
56
- positive: ts.factory.createTrue(),
57
- superfluous: () => ts.factory.createFalse(),
58
- }),
59
- array: (input, arrow) =>
60
- ts.factory.createCallExpression(
61
- IdentifierFactory.join(input, "every"),
62
- undefined,
63
- [arrow],
64
- ),
65
- failure: () => ts.factory.createFalse(),
66
- },
67
- success: ts.factory.createTrue(),
68
- });
19
+ export const CONFIG =
20
+ (options?: Partial<CONFIG.IOptions>) =>
21
+ (importer: FunctionImporter): CheckerProgrammer.IConfig => ({
22
+ functors: "$io",
23
+ unioners: "$iu",
24
+ trace: false,
25
+ path: false,
26
+ equals: !!options?.object,
27
+ numeric: OptionPredicator.numeric({
28
+ numeric: options?.numeric,
29
+ }),
30
+ combiner: () => (type: "and" | "or") => {
31
+ const initial: ts.TrueLiteral | ts.FalseLiteral =
32
+ type === "and"
33
+ ? ts.factory.createTrue()
34
+ : ts.factory.createFalse();
35
+ const binder =
36
+ type === "and"
37
+ ? ts.factory.createLogicalAnd
38
+ : ts.factory.createLogicalOr;
39
+ return (
40
+ _input: ts.Expression,
41
+ binaries: CheckerProgrammer.IBinary[],
42
+ ) =>
43
+ binaries.length
44
+ ? binaries
45
+ .map((binary) => binary.expression)
46
+ .reduce((x, y) => binder(x, y))
47
+ : initial;
48
+ },
49
+ joiner: {
50
+ object:
51
+ options?.object ||
52
+ check_object({
53
+ equals: !!options?.object,
54
+ undefined: OptionPredicator.undefined({
55
+ undefined: options?.undefined,
56
+ }),
57
+ assert: true,
58
+ reduce: ts.factory.createLogicalAnd,
59
+ positive: ts.factory.createTrue(),
60
+ superfluous: () => ts.factory.createFalse(),
61
+ })(importer),
62
+ array: (input, arrow) =>
63
+ ts.factory.createCallExpression(
64
+ IdentifierFactory.join(input, "every"),
65
+ undefined,
66
+ [arrow],
67
+ ),
68
+ failure: () => ts.factory.createFalse(),
69
+ },
70
+ success: ts.factory.createTrue(),
71
+ });
69
72
 
70
73
  export namespace CONFIG {
71
74
  export interface IOptions {
72
75
  numeric: boolean;
76
+ undefined: boolean;
73
77
  object: (entries: IExpressionEntry[]) => ts.Expression;
74
78
  }
75
79
  }
@@ -88,13 +92,14 @@ export namespace IsProgrammer {
88
92
  const config = CONFIG({
89
93
  object: check_object({
90
94
  equals,
95
+ undefined: OptionPredicator.undefined(project.options),
91
96
  assert: true,
92
97
  reduce: ts.factory.createLogicalAnd,
93
98
  positive: ts.factory.createTrue(),
94
99
  superfluous: () => ts.factory.createFalse(),
95
- }),
100
+ })(importer),
96
101
  numeric: OptionPredicator.numeric(project.options),
97
- });
102
+ })(importer);
98
103
  config.trace = equals;
99
104
 
100
105
  if (equals === false)
@@ -137,21 +142,31 @@ export namespace IsProgrammer {
137
142
  export const generate_functors = (
138
143
  project: IProject,
139
144
  importer: FunctionImporter,
140
- ) => CheckerProgrammer.generate_functors(project, CONFIG(), importer);
145
+ ) =>
146
+ CheckerProgrammer.generate_functors(
147
+ project,
148
+ CONFIG()(importer),
149
+ importer,
150
+ );
141
151
 
142
152
  export const generate_unioners = (
143
153
  project: IProject,
144
154
  importer: FunctionImporter,
145
- ) => CheckerProgrammer.generate_unioners(project, CONFIG(), importer);
155
+ ) =>
156
+ CheckerProgrammer.generate_unioners(
157
+ project,
158
+ CONFIG()(importer),
159
+ importer,
160
+ );
146
161
 
147
162
  /* -----------------------------------------------------------
148
163
  DECODERS
149
164
  ----------------------------------------------------------- */
150
165
  export const decode = (project: IProject, importer: FunctionImporter) =>
151
- CheckerProgrammer.decode(project, CONFIG(), importer);
166
+ CheckerProgrammer.decode(project, CONFIG()(importer), importer);
152
167
 
153
- export const decode_object = () =>
154
- CheckerProgrammer.decode_object(CONFIG());
168
+ export const decode_object = (importer: FunctionImporter) =>
169
+ CheckerProgrammer.decode_object(CONFIG()(importer));
155
170
 
156
171
  export function decode_to_json(input: ts.Expression): ts.Expression {
157
172
  return ts.factory.createLogicalAnd(
@@ -716,7 +716,7 @@ export namespace StringifyProgrammer {
716
716
  checker: IsProgrammer.decode(project, importer),
717
717
  decoder: decode_object(),
718
718
  joiner: StringifyJoiner.object(importer),
719
- unionizer: decode_union_object(IsProgrammer.decode_object())(
719
+ unionizer: decode_union_object(IsProgrammer.decode_object(importer))(
720
720
  decode_object(),
721
721
  )((exp) => exp)((value, expected) =>
722
722
  create_throw_error(importer, value, expected),
@@ -4,6 +4,7 @@ import { IdentifierFactory } from "../factories/IdentifierFactory";
4
4
  import { StatementFactory } from "../factories/StatementFactory";
5
5
 
6
6
  import { IProject } from "../transformers/IProject";
7
+ import { ITransformOptions } from "../transformers/ITransformOptions";
7
8
 
8
9
  import { CheckerProgrammer } from "./CheckerProgrammer";
9
10
  import { IsProgrammer } from "./IsProgrammer";
@@ -30,8 +31,8 @@ export namespace ValidateProgrammer {
30
31
  trace: true,
31
32
  numeric: OptionPredicator.numeric(project.options),
32
33
  equals,
33
- combiner: combine(equals)(importer),
34
- joiner: joiner(equals)(importer),
34
+ combiner: combine(project.options)(equals)(importer),
35
+ joiner: joiner(project.options)(equals)(importer),
35
36
  success: ts.factory.createTrue(),
36
37
  },
37
38
  importer,
@@ -85,14 +86,15 @@ export namespace ValidateProgrammer {
85
86
  }
86
87
 
87
88
  const combine =
89
+ (options: ITransformOptions) =>
88
90
  (equals: boolean) =>
89
91
  (importer: FunctionImporter): CheckerProgrammer.IConfig.Combiner =>
90
92
  (explore: CheckerProgrammer.IExplore) => {
91
93
  if (explore.tracable === false)
92
94
  return IsProgrammer.CONFIG({
93
- object: validate_object(equals)(importer),
95
+ object: validate_object(options)(equals)(importer),
94
96
  numeric: true,
95
- }).combiner(explore);
97
+ })(importer).combiner(explore);
96
98
 
97
99
  const path: string = explore.postfix
98
100
  ? `path + ${explore.postfix}`
@@ -131,39 +133,44 @@ const combine =
131
133
  );
132
134
  };
133
135
 
134
- const validate_object = (equals: boolean) => (importer: FunctionImporter) =>
135
- check_object({
136
- equals,
137
- assert: false,
138
- reduce: ts.factory.createLogicalAnd,
139
- positive: ts.factory.createTrue(),
140
- superfluous: (value) =>
141
- create_report_call()(
142
- ts.factory.createAdd(
143
- ts.factory.createIdentifier("path"),
144
- ts.factory.createCallExpression(
145
- importer.use("join"),
146
- undefined,
147
- [ts.factory.createIdentifier("key")],
136
+ const validate_object =
137
+ (options: ITransformOptions) =>
138
+ (equals: boolean) =>
139
+ (importer: FunctionImporter) =>
140
+ check_object({
141
+ equals,
142
+ undefined: OptionPredicator.undefined(options),
143
+ assert: false,
144
+ reduce: ts.factory.createLogicalAnd,
145
+ positive: ts.factory.createTrue(),
146
+ superfluous: (value) =>
147
+ create_report_call()(
148
+ ts.factory.createAdd(
149
+ ts.factory.createIdentifier("path"),
150
+ ts.factory.createCallExpression(
151
+ importer.use("join"),
152
+ undefined,
153
+ [ts.factory.createIdentifier("key")],
154
+ ),
148
155
  ),
156
+ "undefined",
157
+ value,
149
158
  ),
150
- "undefined",
151
- value,
152
- ),
153
- halt: (expr) =>
154
- ts.factory.createLogicalOr(
155
- ts.factory.createStrictEquality(
156
- ts.factory.createFalse(),
157
- ts.factory.createIdentifier("exceptionable"),
159
+ halt: (expr) =>
160
+ ts.factory.createLogicalOr(
161
+ ts.factory.createStrictEquality(
162
+ ts.factory.createFalse(),
163
+ ts.factory.createIdentifier("exceptionable"),
164
+ ),
165
+ expr,
158
166
  ),
159
- expr,
160
- ),
161
- });
167
+ })(importer);
162
168
 
163
169
  const joiner =
170
+ (options: ITransformOptions) =>
164
171
  (equals: boolean) =>
165
172
  (importer: FunctionImporter): CheckerProgrammer.IConfig.IJoiner => ({
166
- object: validate_object(equals)(importer),
173
+ object: validate_object(options)(equals)(importer),
167
174
  array: (input, arrow) =>
168
175
  check_everything(
169
176
  ts.factory.createCallExpression(
@@ -12,4 +12,8 @@ export namespace OptionPredicator {
12
12
  export function finite(options: ITransformOptions): boolean {
13
13
  return options.finite === true;
14
14
  }
15
+
16
+ export function undefined(options: ITransformOptions): boolean {
17
+ return options.undefined !== false;
18
+ }
15
19
  }
@@ -3,6 +3,7 @@ import ts from "typescript";
3
3
  import { IdentifierFactory } from "../../factories/IdentifierFactory";
4
4
  import { StatementFactory } from "../../factories/StatementFactory";
5
5
 
6
+ import { FunctionImporter } from "../helpers/FunctionImporeter";
6
7
  import { IExpressionEntry } from "../helpers/IExpressionEntry";
7
8
  import { check_everything } from "./check_everything";
8
9
  import { check_object } from "./check_object";
@@ -13,26 +14,47 @@ import { metadata_to_pattern } from "./metadata_to_pattern";
13
14
  */
14
15
  export const check_dynamic_properties =
15
16
  (props: check_object.IProps) =>
17
+ (importer: FunctionImporter) =>
16
18
  (
17
19
  regular: IExpressionEntry[],
18
20
  dynamic: IExpressionEntry[],
19
21
  ): ts.Expression => {
20
- const length =
22
+ const length = IdentifierFactory.join(
23
+ ts.factory.createCallExpression(
24
+ ts.factory.createIdentifier("Object.keys"),
25
+ undefined,
26
+ [ts.factory.createIdentifier("input")],
27
+ ),
28
+ "length",
29
+ );
30
+ const left: ts.Expression | null =
21
31
  props.equals === true && dynamic.length === 0
22
- ? ts.factory.createStrictEquality(
23
- ts.factory.createNumericLiteral(
24
- regular.filter((r) => r.meta.required).length,
25
- ),
26
- IdentifierFactory.join(
27
- ts.factory.createCallExpression(
28
- ts.factory.createIdentifier("Object.keys"),
29
- undefined,
30
- [ts.factory.createIdentifier("input")],
32
+ ? props.undefined === true ||
33
+ regular.every((r) => r.meta.required)
34
+ ? ts.factory.createStrictEquality(
35
+ ts.factory.createNumericLiteral(
36
+ regular.filter((r) => r.meta.required).length,
31
37
  ),
32
- "length",
33
- ),
34
- )
38
+ length,
39
+ )
40
+ : ts.factory.createCallExpression(
41
+ importer.use("is_between"),
42
+ [],
43
+ [
44
+ length,
45
+ ts.factory.createNumericLiteral(
46
+ regular.filter((r) => r.meta.required).length,
47
+ ),
48
+ ts.factory.createNumericLiteral(regular.length),
49
+ ],
50
+ )
35
51
  : null;
52
+ if (
53
+ props.undefined === false &&
54
+ left !== null &&
55
+ regular.every((r) => r.meta.required)
56
+ )
57
+ return left;
36
58
 
37
59
  const criteria = props.entries
38
60
  ? ts.factory.createCallExpression(props.entries, undefined, [
@@ -58,7 +80,11 @@ export const check_dynamic_properties =
58
80
  const right: ts.Expression = (props.halt || ((elem) => elem))(
59
81
  props.assert ? criteria : check_everything(criteria),
60
82
  );
61
- return length ? ts.factory.createLogicalOr(length, right) : right;
83
+ return left
84
+ ? (props.undefined
85
+ ? ts.factory.createLogicalOr
86
+ : ts.factory.createLogicalAnd)(left, right)
87
+ : right;
62
88
  };
63
89
 
64
90
  const check_dynamic_property =
@@ -89,13 +115,14 @@ const check_dynamic_property =
89
115
  ts.factory.createIdentifier("input[key]"),
90
116
  ),
91
117
  );
92
- add(
93
- ts.factory.createStrictEquality(
94
- ts.factory.createIdentifier("undefined"),
95
- value,
96
- ),
97
- props.positive,
98
- );
118
+ if (props.undefined === true)
119
+ add(
120
+ ts.factory.createStrictEquality(
121
+ ts.factory.createIdentifier("undefined"),
122
+ value,
123
+ ),
124
+ props.positive,
125
+ );
99
126
  for (const entry of dynamic)
100
127
  add(
101
128
  ts.factory.createCallExpression(
@@ -1,5 +1,6 @@
1
1
  import ts from "typescript";
2
2
 
3
+ import { FunctionImporter } from "../helpers/FunctionImporeter";
3
4
  import { IExpressionEntry } from "../helpers/IExpressionEntry";
4
5
  import { check_dynamic_properties } from "./check_dynamic_properties";
5
6
  import { check_everything } from "./check_everything";
@@ -8,7 +9,9 @@ import { check_everything } from "./check_everything";
8
9
  * @internal
9
10
  */
10
11
  export const check_object =
11
- (props: check_object.IProps) => (entries: IExpressionEntry[]) => {
12
+ (props: check_object.IProps) =>
13
+ (importer: FunctionImporter) =>
14
+ (entries: IExpressionEntry[]) => {
12
15
  // PREPARE ASSETS
13
16
  const regular = entries.filter((entry) => entry.key.isSoleLiteral());
14
17
  const dynamic = entries.filter((entry) => !entry.key.isSoleLiteral());
@@ -19,13 +22,14 @@ export const check_object =
19
22
  return regular.length === 0 ? props.positive : reduce(props)(flags);
20
23
 
21
24
  // CHECK DYNAMIC PROPERTIES
22
- flags.push(check_dynamic_properties(props)(regular, dynamic));
25
+ flags.push(check_dynamic_properties(props)(importer)(regular, dynamic));
23
26
  return reduce(props)(flags);
24
27
  };
25
28
  export namespace check_object {
26
29
  export interface IProps {
27
30
  equals: boolean;
28
31
  assert: boolean;
32
+ undefined: boolean;
29
33
  halt?: (exp: ts.Expression) => ts.Expression;
30
34
  reduce: (a: ts.Expression, b: ts.Expression) => ts.Expression;
31
35
  positive: ts.Expression;
@@ -44,4 +44,15 @@ export interface ITransformOptions {
44
44
  * @default false
45
45
  */
46
46
  functional?: boolean;
47
+
48
+ /**
49
+ * Whether to check undefined value or not.
50
+ *
51
+ * JavaScript can assign `undefined` value to a specific property and it is an
52
+ * issue when validating without allowing superfluous properties. Should undefined
53
+ * value assigned superfluous property be allowed or not?
54
+ *
55
+ * @default true
56
+ */
57
+ undefined?: boolean;
47
58
  }