typia 5.3.7-dev.20231230 → 5.3.8-dev.20240103

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 (47) hide show
  1. package/lib/json.d.ts +12 -8
  2. package/lib/json.js.map +1 -1
  3. package/lib/programmers/internal/application_array.js +42 -38
  4. package/lib/programmers/internal/application_array.js.map +1 -1
  5. package/lib/programmers/internal/application_boolean.js +19 -10
  6. package/lib/programmers/internal/application_boolean.js.map +1 -1
  7. package/lib/programmers/internal/application_constant.js +6 -13
  8. package/lib/programmers/internal/application_constant.js.map +1 -1
  9. package/lib/programmers/internal/application_escaped.d.ts +1 -1
  10. package/lib/programmers/internal/application_escaped.js +15 -17
  11. package/lib/programmers/internal/application_escaped.js.map +1 -1
  12. package/lib/programmers/internal/application_native.js +6 -15
  13. package/lib/programmers/internal/application_native.js.map +1 -1
  14. package/lib/programmers/internal/application_number.js +82 -75
  15. package/lib/programmers/internal/application_number.js.map +1 -1
  16. package/lib/programmers/internal/application_object.js +23 -20
  17. package/lib/programmers/internal/application_object.js.map +1 -1
  18. package/lib/programmers/internal/application_schema.js +14 -25
  19. package/lib/programmers/internal/application_schema.js.map +1 -1
  20. package/lib/programmers/internal/application_string.js +52 -45
  21. package/lib/programmers/internal/application_string.js.map +1 -1
  22. package/lib/programmers/internal/application_templates.js +3 -12
  23. package/lib/programmers/internal/application_templates.js.map +1 -1
  24. package/lib/programmers/internal/application_tuple.js +5 -1
  25. package/lib/programmers/internal/application_tuple.js.map +1 -1
  26. package/lib/programmers/json/JsonApplicationProgrammer.d.ts +1 -0
  27. package/lib/programmers/json/JsonApplicationProgrammer.js +5 -5
  28. package/lib/programmers/json/JsonApplicationProgrammer.js.map +1 -1
  29. package/lib/schemas/json/IJsonApplication.d.ts +1 -0
  30. package/lib/transformers/features/json/JsonApplicationTransformer.js +36 -17
  31. package/lib/transformers/features/json/JsonApplicationTransformer.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/json.ts +12 -7
  34. package/src/programmers/internal/application_array.ts +13 -13
  35. package/src/programmers/internal/application_boolean.ts +7 -2
  36. package/src/programmers/internal/application_constant.ts +0 -1
  37. package/src/programmers/internal/application_escaped.ts +2 -3
  38. package/src/programmers/internal/application_native.ts +3 -7
  39. package/src/programmers/internal/application_number.ts +13 -10
  40. package/src/programmers/internal/application_object.ts +20 -10
  41. package/src/programmers/internal/application_schema.ts +19 -34
  42. package/src/programmers/internal/application_string.ts +13 -10
  43. package/src/programmers/internal/application_templates.ts +0 -1
  44. package/src/programmers/internal/application_tuple.ts +0 -1
  45. package/src/programmers/json/JsonApplicationProgrammer.ts +5 -6
  46. package/src/schemas/json/IJsonApplication.ts +1 -0
  47. package/src/transformers/features/json/JsonApplicationTransformer.ts +47 -34
@@ -12,14 +12,12 @@ import { application_schema } from "./application_schema";
12
12
  export const application_array =
13
13
  (options: JsonApplicationProgrammer.IOptions) =>
14
14
  (components: IJsonComponents) =>
15
- (array: MetadataArray) =>
16
- (attribute: IJsonSchema.IAttribute): IJsonSchema.IArray[] => {
15
+ (array: MetadataArray): IJsonSchema.IArray[] => {
17
16
  // BASE SCHEMA
18
17
  const items: IJsonSchema = application_schema(options)(false)(components)(
19
18
  array.type.value,
20
- )(attribute);
19
+ )({});
21
20
  const base: IJsonSchema.IArray = {
22
- ...attribute,
23
21
  type: "array",
24
22
  items: null!,
25
23
  };
@@ -31,7 +29,7 @@ export const application_array =
31
29
 
32
30
  // CONSIDER TYPE TAGS
33
31
  const union: IJsonSchema.IArray[] = array.tags.map(
34
- (row) => application_array_tags({ ...base })(row)!,
32
+ (row) => application_array_tags(options)({ ...base })(row)!,
35
33
  );
36
34
  const map: Map<string, IJsonSchema.IArray> = new Map(
37
35
  union.map((u) => [JSON.stringify(u), u]),
@@ -40,6 +38,7 @@ export const application_array =
40
38
  };
41
39
 
42
40
  const application_array_tags =
41
+ (options: JsonApplicationProgrammer.IOptions) =>
43
42
  (schema: IJsonSchema.IArray) =>
44
43
  (row: IMetadataTypeTag[]): IJsonSchema.IArray => {
45
44
  for (const tag of row.slice().sort((a, b) => a.kind.localeCompare(b.kind)))
@@ -47,13 +46,14 @@ const application_array_tags =
47
46
  schema.minItems = tag.value;
48
47
  else if (tag.kind === "maxItems" && typeof tag.value === "number")
49
48
  schema.maxItems = tag.value;
50
- schema["x-typia-typeTags"] = row.map((tag) => ({
51
- target: tag.target,
52
- name: tag.name,
53
- kind: tag.kind,
54
- value: tag.value,
55
- validate: tag.validate,
56
- exclusive: tag.exclusive,
57
- }));
49
+ if (options.surplus)
50
+ schema["x-typia-typeTags"] = row.map((tag) => ({
51
+ target: tag.target,
52
+ name: tag.name,
53
+ kind: tag.kind,
54
+ value: tag.value,
55
+ validate: tag.validate,
56
+ exclusive: tag.exclusive,
57
+ }));
58
58
  return schema;
59
59
  };
@@ -2,16 +2,17 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
2
2
  import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
3
3
 
4
4
  import { IJsonSchema } from "../../module";
5
+ import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
5
6
  import { application_default } from "./application_default";
6
7
 
7
8
  /**
8
9
  * @internal
9
10
  */
10
11
  export const application_boolean =
12
+ (options: JsonApplicationProgrammer.IOptions) =>
11
13
  (atomic: MetadataAtomic) =>
12
14
  (attribute: IJsonSchema.IAttribute): IJsonSchema.IBoolean[] => {
13
15
  const base: IJsonSchema.IBoolean = {
14
- ...attribute,
15
16
  default: application_default(attribute)(
16
17
  (alias) => alias === "true" || alias === "false",
17
18
  )((str) => Boolean(str)),
@@ -25,6 +26,10 @@ export const application_boolean =
25
26
  return defaultTags.map((tag) => ({
26
27
  ...base,
27
28
  default: tag.value,
28
- "x-typia-typeTags": defaultTags,
29
+ ...(options.surplus
30
+ ? {
31
+ "x-typia-typeTags": defaultTags,
32
+ }
33
+ : {}),
29
34
  }));
30
35
  };
@@ -9,7 +9,6 @@ import { application_default } from "./application_default";
9
9
  export const application_constant =
10
10
  (constant: MetadataConstant) =>
11
11
  (attribute: IJsonSchema.IAttribute): IJsonSchema.IEnumeration<any> => ({
12
- ...attribute,
13
12
  type: constant.type,
14
13
  enum: constant.values as any,
15
14
  default: application_default(attribute)((alias) =>
@@ -9,11 +9,10 @@ export const application_escaped =
9
9
  (options: JsonApplicationProgrammer.IOptions) =>
10
10
  <BlockNever extends boolean>(blockNever: BlockNever) =>
11
11
  (components: IJsonComponents) =>
12
- (resolved: MetadataEscaped) =>
13
- (attribute: IJsonSchema.IAttribute): IJsonSchema[] => {
12
+ (resolved: MetadataEscaped): IJsonSchema[] => {
14
13
  const output = application_schema(options)(blockNever)(components)(
15
14
  resolved.returns,
16
- )(attribute);
15
+ )({});
17
16
  if (output === null) return [];
18
17
 
19
18
  if (is_date(new Set())(resolved.original)) {
@@ -11,14 +11,11 @@ export const application_native =
11
11
  (options: JsonApplicationProgrammer.IOptions) =>
12
12
  (components: IJsonComponents) =>
13
13
  (name: string) =>
14
- (props: {
15
- nullable: boolean;
16
- attribute: IJsonSchema.IAttribute;
17
- }): IJsonSchema.IReference => {
14
+ (nullable: boolean): IJsonSchema.IReference => {
18
15
  const key: string =
19
16
  options.purpose === "ajv"
20
17
  ? name
21
- : `${name}${props.nullable ? ".Nullable" : ""}`;
18
+ : `${name}${nullable ? ".Nullable" : ""}`;
22
19
  if (components.schemas?.[key] === undefined) {
23
20
  components.schemas ??= {};
24
21
  components.schemas[key] ??= {
@@ -28,11 +25,10 @@ export const application_native =
28
25
  ? `${JSON_COMPONENTS_PREFIX}/objects/${key}`
29
26
  : undefined,
30
27
  properties: {},
31
- nullable: options.purpose === "swagger" ? props.nullable : undefined,
28
+ nullable: options.purpose === "swagger" ? nullable : undefined,
32
29
  };
33
30
  }
34
31
  return {
35
- ...props.attribute,
36
32
  $ref: `${JSON_COMPONENTS_PREFIX}/objects/${key}`,
37
33
  };
38
34
  };
@@ -2,6 +2,7 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
2
2
  import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
3
3
 
4
4
  import { IJsonSchema } from "../../module";
5
+ import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
5
6
  import { application_default } from "./application_default";
6
7
 
7
8
  type Schema = IJsonSchema.INumber | IJsonSchema.IInteger;
@@ -10,11 +11,11 @@ type Schema = IJsonSchema.INumber | IJsonSchema.IInteger;
10
11
  * @internal
11
12
  */
12
13
  export const application_number =
14
+ (options: JsonApplicationProgrammer.IOptions) =>
13
15
  (atomic: MetadataAtomic) =>
14
16
  (attribute: IJsonSchema.IAttribute): Array<Schema> => {
15
17
  // BASE CONFIGURATION
16
18
  const base: Schema = {
17
- ...attribute,
18
19
  type: "number",
19
20
  };
20
21
  const out = (schema: Schema) => {
@@ -39,7 +40,7 @@ export const application_number =
39
40
 
40
41
  // CONSIDER TYPE TAGS
41
42
  const union: Schema[] = atomic.tags.map(
42
- (row) => application_number_tags({ ...base })(row)!,
43
+ (row) => application_number_tags(options)({ ...base })(row)!,
43
44
  );
44
45
  const map: Map<string, Schema> = new Map(
45
46
  union.map((u) => [JSON.stringify(u), u]),
@@ -48,6 +49,7 @@ export const application_number =
48
49
  };
49
50
 
50
51
  const application_number_tags =
52
+ (options: JsonApplicationProgrammer.IOptions) =>
51
53
  (base: Schema) =>
52
54
  (row: IMetadataTypeTag[]): Schema => {
53
55
  for (const tag of row
@@ -82,13 +84,14 @@ const application_number_tags =
82
84
  else if (tag.kind === "default" && typeof tag.value === "number")
83
85
  base.default = tag.value;
84
86
  }
85
- base["x-typia-typeTags"] = row.map((tag) => ({
86
- target: tag.target,
87
- name: tag.name,
88
- kind: tag.kind,
89
- value: tag.value,
90
- validate: tag.validate,
91
- exclusive: tag.exclusive,
92
- }));
87
+ if (options.surplus)
88
+ base["x-typia-typeTags"] = row.map((tag) => ({
89
+ target: tag.target,
90
+ name: tag.name,
91
+ kind: tag.kind,
92
+ value: tag.value,
93
+ validate: tag.validate,
94
+ exclusive: tag.exclusive,
95
+ }));
93
96
  return base;
94
97
  };
@@ -84,11 +84,15 @@ const create_object_schema =
84
84
  : undefined;
85
85
  })(),
86
86
  description: property.description ?? undefined,
87
- "x-typia-jsDocTags": property.jsDocTags.length
88
- ? property.jsDocTags
89
- : undefined,
90
- "x-typia-required": property.value.required,
91
- "x-typia-optional": property.value.optional,
87
+ ...(options.surplus
88
+ ? {
89
+ "x-typia-jsDocTags": property.jsDocTags.length
90
+ ? property.jsDocTags
91
+ : undefined,
92
+ "x-typia-required": property.value.required,
93
+ "x-typia-optional": property.value.optional,
94
+ }
95
+ : {}),
92
96
  });
93
97
 
94
98
  if (schema === null) continue;
@@ -125,12 +129,14 @@ const create_object_schema =
125
129
  "x-typia-jsDocTags": obj.jsDocTags,
126
130
  ...(options.purpose === "ajv"
127
131
  ? extraProps
128
- : {
132
+ : options.surplus
133
+ ? {
129
134
  // swagger can't express patternProperties
130
135
  "x-typia-additionalProperties": extraProps.additionalProperties,
131
136
  "x-typia-patternProperties": extraProps.patternProperties,
132
137
  additionalProperties: join(options)(components)(extraMeta),
133
- }),
138
+ }
139
+ : {}),
134
140
  };
135
141
  };
136
142
 
@@ -153,9 +159,13 @@ const join =
153
159
  .map((tuple) => tuple[0])
154
160
  .reduce((x, y) => Metadata.merge(x, y));
155
161
  return (
156
- application_schema(options)(true)(components)(meta)({
157
- "x-typia-required": false,
158
- }) ?? undefined
162
+ application_schema(options)(true)(components)(meta)(
163
+ options.surplus
164
+ ? {
165
+ "x-typia-required": false,
166
+ }
167
+ : {},
168
+ ) ?? undefined
159
169
  );
160
170
  };
161
171
 
@@ -49,10 +49,10 @@ export const application_schema =
49
49
 
50
50
  const insert =
51
51
  meta.nullable && options.purpose === "swagger"
52
- ? (s: IJsonSchema) =>
52
+ ? (schema: IJsonSchema) =>
53
53
  union.push({
54
- ...s,
55
- nullable: (s as IJsonSchema.ISignificant<any>).type
54
+ ...schema,
55
+ nullable: (schema as IJsonSchema.ISignificant<any>).type
56
56
  ? true
57
57
  : undefined,
58
58
  } as IJsonSchema)
@@ -61,9 +61,7 @@ export const application_schema =
61
61
  // toJSON() METHOD
62
62
  if (meta.escaped !== null)
63
63
  union.push(
64
- ...application_escaped(options)(blockNever)(components)(meta.escaped)(
65
- attribute,
66
- ),
64
+ ...application_escaped(options)(blockNever)(components)(meta.escaped),
67
65
  );
68
66
 
69
67
  // ATOMIC TYPES
@@ -80,17 +78,15 @@ export const application_schema =
80
78
  for (const a of meta.atomics)
81
79
  if (a.type === "bigint") throw new TypeError(NO_BIGINT);
82
80
  else if (a.type === "boolean")
83
- application_boolean(a)(attribute).forEach(insert);
81
+ application_boolean(options)(a)(attribute).forEach(insert);
84
82
  else if (a.type === "number")
85
- application_number(a)(attribute).forEach(insert);
83
+ application_number(options)(a)(attribute).forEach(insert);
86
84
  else if (a.type === "string")
87
- application_string(meta)(a)(attribute).forEach(insert);
85
+ application_string(options)(meta)(a)(attribute).forEach(insert);
88
86
 
89
87
  // ARRAY
90
88
  for (const array of meta.arrays)
91
- application_array(options)(components)(array)(attribute).forEach((s) =>
92
- insert(s),
93
- );
89
+ application_array(options)(components)(array).forEach(insert);
94
90
 
95
91
  // TUPLE
96
92
  for (const tuple of meta.tuples)
@@ -104,7 +100,7 @@ export const application_schema =
104
100
  else if (type === "bigint") throw new TypeError(NO_BIGINT);
105
101
  else if (type === "boolean")
106
102
  insert(
107
- application_boolean(
103
+ application_boolean(options)(
108
104
  MetadataAtomic.create({
109
105
  type: "boolean",
110
106
  tags: [],
@@ -113,7 +109,7 @@ export const application_schema =
113
109
  );
114
110
  else if (type === "number")
115
111
  insert(
116
- application_number(
112
+ application_number(options)(
117
113
  MetadataAtomic.create({
118
114
  type: "number",
119
115
  tags: [],
@@ -122,7 +118,7 @@ export const application_schema =
122
118
  );
123
119
  else if (type === "string")
124
120
  insert(
125
- application_string(meta)(
121
+ application_string(options)(meta)(
126
122
  MetadataAtomic.create({
127
123
  type: "string",
128
124
  tags: [],
@@ -130,26 +126,11 @@ export const application_schema =
130
126
  )(attribute)[0]!,
131
127
  );
132
128
  } else
133
- insert(
134
- application_native(options)(components)(native)({
135
- nullable: meta.nullable,
136
- attribute,
137
- }),
138
- );
129
+ insert(application_native(options)(components)(native)(meta.nullable));
139
130
  if (meta.sets.length)
140
- insert(
141
- application_native(options)(components)(`Set`)({
142
- nullable: meta.nullable,
143
- attribute,
144
- }),
145
- );
131
+ insert(application_native(options)(components)(`Set`)(meta.nullable));
146
132
  if (meta.maps.length)
147
- insert(
148
- application_native(options)(components)(`Map`)({
149
- nullable: meta.nullable,
150
- attribute,
151
- }),
152
- );
133
+ insert(application_native(options)(components)(`Map`)(meta.nullable));
153
134
 
154
135
  // OBJECT
155
136
  for (const obj of meta.objects)
@@ -173,7 +154,11 @@ export const application_schema =
173
154
  ...attribute,
174
155
  type: undefined,
175
156
  };
176
- else if (union.length === 1) return union[0]!;
157
+ else if (union.length === 1)
158
+ return {
159
+ ...union[0]!,
160
+ ...attribute,
161
+ };
177
162
  return { oneOf: union, ...attribute };
178
163
  };
179
164
 
@@ -3,18 +3,19 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
3
3
  import { Metadata } from "../../schemas/metadata/Metadata";
4
4
  import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
5
5
 
6
+ import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
6
7
  import { application_default_string } from "./application_default_string";
7
8
 
8
9
  /**
9
10
  * @internal
10
11
  */
11
12
  export const application_string =
13
+ (options: JsonApplicationProgrammer.IOptions) =>
12
14
  (meta: Metadata) =>
13
15
  (atomic: MetadataAtomic) =>
14
16
  (attribute: IJsonSchema.IAttribute): IJsonSchema.IString[] => {
15
17
  // DEFAULT CONFIGURATION
16
18
  const base: IJsonSchema.IString = {
17
- ...attribute,
18
19
  type: "string",
19
20
  };
20
21
  const out = (schema: IJsonSchema.IString) => {
@@ -25,7 +26,7 @@ export const application_string =
25
26
 
26
27
  // CONSIDER TYPE TAGS
27
28
  const union: IJsonSchema.IString[] = atomic.tags.map(
28
- (row) => application_string_tags({ ...base })(row)!,
29
+ (row) => application_string_tags(options)({ ...base })(row)!,
29
30
  );
30
31
  const map: Map<string, IJsonSchema.IString> = new Map(
31
32
  union.map((u) => [JSON.stringify(u), u]),
@@ -34,6 +35,7 @@ export const application_string =
34
35
  };
35
36
 
36
37
  const application_string_tags =
38
+ (options: JsonApplicationProgrammer.IOptions) =>
37
39
  (base: IJsonSchema.IString) =>
38
40
  (row: IMetadataTypeTag[]): IJsonSchema.IString | null => {
39
41
  for (const tag of row.slice().sort((a, b) => a.kind.localeCompare(b.kind)))
@@ -46,13 +48,14 @@ const application_string_tags =
46
48
  else if (tag.kind === "pattern") base.pattern = tag.value;
47
49
  else if (tag.kind === "default" && typeof tag.value === "string")
48
50
  base.default = tag.value;
49
- base["x-typia-typeTags"] = row.map((tag) => ({
50
- target: tag.target,
51
- name: tag.name,
52
- kind: tag.kind,
53
- value: tag.value,
54
- validate: tag.validate,
55
- exclusive: tag.exclusive,
56
- }));
51
+ if (options.surplus)
52
+ base["x-typia-typeTags"] = row.map((tag) => ({
53
+ target: tag.target,
54
+ name: tag.name,
55
+ kind: tag.kind,
56
+ value: tag.value,
57
+ validate: tag.validate,
58
+ exclusive: tag.exclusive,
59
+ }));
57
60
  return base;
58
61
  };
@@ -13,7 +13,6 @@ export const application_templates =
13
13
  // CONSTRUCT PATTERN
14
14
  const output: IJsonSchema.IString = {
15
15
  type: "string",
16
- ...attribute,
17
16
  };
18
17
  output.pattern = metadata_to_pattern(true)(meta);
19
18
 
@@ -20,7 +20,6 @@ export const application_tuple =
20
20
  type: "array",
21
21
  items: tuple.type.elements.map((meta, i) =>
22
22
  application_schema(options)(false)(components)(meta.rest ?? meta)({
23
- ...attribute,
24
23
  "x-typia-rest":
25
24
  i === tuple.type.elements.length - 1 && meta.rest !== null,
26
25
  "x-typia-required": meta.required,
@@ -10,18 +10,17 @@ import { application_schema } from "../internal/application_schema";
10
10
  export namespace JsonApplicationProgrammer {
11
11
  export interface IOptions {
12
12
  purpose: "ajv" | "swagger";
13
+ surplus: boolean;
13
14
  }
14
15
 
15
16
  /**
16
17
  * @internal
17
18
  */
18
19
  export namespace IOptions {
19
- export const complement = (options?: Partial<IOptions>): IOptions => {
20
- const purpose: "swagger" | "ajv" = options?.purpose ?? "swagger";
21
- return {
22
- purpose,
23
- };
24
- };
20
+ export const complement = (options?: Partial<IOptions>): IOptions => ({
21
+ purpose: options?.purpose ?? "swagger",
22
+ surplus: options?.surplus ?? false,
23
+ });
25
24
  }
26
25
 
27
26
  export const write =
@@ -5,4 +5,5 @@ export interface IJsonApplication {
5
5
  schemas: IJsonSchema[];
6
6
  components: IJsonComponents;
7
7
  purpose: "swagger" | "ajv";
8
+ surplus: boolean;
8
9
  }
@@ -45,13 +45,20 @@ export namespace JsonApplicationTransformer {
45
45
  });
46
46
 
47
47
  // ADDITIONAL PARAMETERS
48
- const purpose: "swagger" | "ajv" = get_parameter(
49
- project.checker,
50
- "Purpose",
51
- expression.typeArguments[1],
52
- (str) => str === "swagger" || str === "ajv",
53
- () => "swagger",
54
- );
48
+ const purpose: "swagger" | "ajv" = get_parameter<"swagger" | "ajv">({
49
+ checker: project.checker,
50
+ name: "Purpose",
51
+ is: (str) => str === "swagger" || str === "ajv",
52
+ cast: (str) => str as "swagger" | "ajv",
53
+ default: () => "swagger",
54
+ })(expression.typeArguments[1]);
55
+ const surplus: boolean = get_parameter<boolean>({
56
+ checker: project.checker,
57
+ name: "Surplus",
58
+ is: (str) => str === "true" || str === "false",
59
+ cast: (str) => str === "true",
60
+ default: () => false,
61
+ })(expression.typeArguments[2]);
55
62
 
56
63
  //----
57
64
  // GENERATORS
@@ -86,36 +93,42 @@ export namespace JsonApplicationTransformer {
86
93
  // APPLICATION
87
94
  const app: IJsonApplication = JsonApplicationProgrammer.write({
88
95
  purpose,
96
+ surplus,
89
97
  })(metadatas);
90
-
91
- // RETURNS WITH LITERAL EXPRESSION
92
98
  return LiteralFactory.generate(app);
93
99
  };
94
100
 
95
- const get_parameter = <T extends string>(
96
- checker: ts.TypeChecker,
97
- name: string,
98
- node: ts.TypeNode | undefined,
99
- predicator: (value: string) => boolean,
100
- defaulter: () => T,
101
- ): T => {
102
- if (!node) return defaulter();
103
-
104
- // CHECK LITERAL TYPE
105
- const type: ts.Type = checker.getTypeFromTypeNode(node);
106
- if (!type.isLiteral())
107
- throw new TransformerError({
108
- code: "typia.json.application",
109
- message: `generic argument "${name}" must be constant.`,
110
- });
101
+ const get_parameter =
102
+ <Value>(props: {
103
+ checker: ts.TypeChecker;
104
+ name: string;
105
+ is: (value: string) => boolean;
106
+ cast: (value: string) => Value;
107
+ default: () => Value;
108
+ }) =>
109
+ (node: ts.TypeNode | undefined): Value => {
110
+ if (!node) return props.default();
111
+
112
+ // CHECK LITERAL TYPE
113
+ const type: ts.Type = props.checker.getTypeFromTypeNode(node);
114
+ if (
115
+ !type.isLiteral() &&
116
+ (type.getFlags() & ts.TypeFlags.BooleanLiteral) === 0
117
+ )
118
+ throw new TransformerError({
119
+ code: "typia.json.application",
120
+ message: `generic argument "${props.name}" must be constant.`,
121
+ });
111
122
 
112
- // GET VALUE AND VALIDATE IT
113
- const value = type.value;
114
- if (typeof value !== "string" || predicator(value) === false)
115
- throw new TransformerError({
116
- code: "typia.json.application",
117
- message: `invalid value on generic argument "${name}".`,
118
- });
119
- return value as T;
120
- };
123
+ // GET VALUE AND VALIDATE IT
124
+ const value = type.isLiteral()
125
+ ? type.value
126
+ : props.checker.typeToString(type);
127
+ if (typeof value !== "string" || props.is(value) === false)
128
+ throw new TransformerError({
129
+ code: "typia.json.application",
130
+ message: `invalid value on generic argument "${props.name}".`,
131
+ });
132
+ return props.cast(value);
133
+ };
121
134
  }