typia 13.2.0 → 13.3.0

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 (92) hide show
  1. package/lib/http.d.ts +3 -3
  2. package/lib/http.js.map +1 -1
  3. package/lib/http.mjs.map +1 -1
  4. package/lib/internal/_assertGuard.js +13 -3
  5. package/lib/internal/_assertGuard.js.map +1 -1
  6. package/lib/internal/_assertGuard.mjs +4 -2
  7. package/lib/internal/_assertGuard.mjs.map +1 -1
  8. package/lib/internal/_isFormatIdnHostname.js +5 -1
  9. package/lib/internal/_isFormatIdnHostname.js.map +1 -1
  10. package/lib/internal/_isFormatIdnHostname.mjs +1 -1
  11. package/lib/internal/_isFormatIdnHostname.mjs.map +1 -1
  12. package/lib/internal/_isFormatTime.js +19 -2
  13. package/lib/internal/_isFormatTime.js.map +1 -1
  14. package/lib/internal/_isFormatTime.mjs +9 -2
  15. package/lib/internal/_isFormatTime.mjs.map +1 -1
  16. package/lib/internal/_randomArray.js +37 -4
  17. package/lib/internal/_randomArray.js.map +1 -1
  18. package/lib/internal/_randomArray.mjs +16 -3
  19. package/lib/internal/_randomArray.mjs.map +1 -1
  20. package/lib/internal/_randomFormatByte.js +15 -12
  21. package/lib/internal/_randomFormatByte.js.map +1 -1
  22. package/lib/internal/_randomFormatByte.mjs +11 -10
  23. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  24. package/lib/internal/_randomFormatDatetime.mjs +1 -1
  25. package/lib/internal/_randomFormatHostname.d.ts +2 -2
  26. package/lib/internal/_randomFormatHostname.js +2 -2
  27. package/lib/internal/_randomFormatHostname.mjs +2 -2
  28. package/lib/internal/_randomFormatHostname.mjs.map +1 -1
  29. package/lib/internal/_randomFormatIdnHostname.js +9 -10
  30. package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
  31. package/lib/internal/_randomFormatIdnHostname.mjs +3 -4
  32. package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
  33. package/lib/internal/_randomFormatRegex.js +4 -4
  34. package/lib/internal/_randomFormatRegex.js.map +1 -1
  35. package/lib/internal/_randomFormatRegex.mjs +1 -2
  36. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  37. package/lib/internal/_randomFormatTime.js +15 -10
  38. package/lib/internal/_randomFormatTime.js.map +1 -1
  39. package/lib/internal/_randomFormatTime.mjs +6 -3
  40. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  41. package/lib/internal/private/__randomComposition.d.ts +8 -0
  42. package/lib/internal/private/__randomComposition.js +21 -1
  43. package/lib/internal/private/__randomComposition.js.map +1 -1
  44. package/lib/internal/private/__randomComposition.mjs +18 -1
  45. package/lib/internal/private/__randomComposition.mjs.map +1 -1
  46. package/lib/json.d.ts +2 -2
  47. package/lib/json.js.map +1 -1
  48. package/lib/json.mjs.map +1 -1
  49. package/lib/module.d.ts +28 -13
  50. package/lib/module.js.map +1 -1
  51. package/lib/module.mjs.map +1 -1
  52. package/lib/notations.d.ts +4 -4
  53. package/lib/notations.js.map +1 -1
  54. package/lib/notations.mjs.map +1 -1
  55. package/lib/plain.d.ts +3 -3
  56. package/lib/plain.js.map +1 -1
  57. package/lib/plain.mjs.map +1 -1
  58. package/lib/protobuf.d.ts +2 -2
  59. package/lib/protobuf.js.map +1 -1
  60. package/lib/protobuf.mjs.map +1 -1
  61. package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +17 -4
  62. package/native/cmd/ttsc-typia/create_assert_error_factory_arity_test.go +309 -0
  63. package/native/cmd/ttsc-typia/local_function_named_like_typia_operation_transform_test.go +185 -0
  64. package/native/cmd/ttsc-typia/recursive_conditional_alias_name_transform_test.go +307 -0
  65. package/native/cmd/ttsc-typia/shadowed_typia_module_declaration_diagnostic_test.go +152 -0
  66. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +1 -3
  67. package/native/cmd/ttsc-typia/transform_helpers_test.go +92 -26
  68. package/native/core/factories/FormatCheatSheet.go +2 -2
  69. package/native/core/factories/MetadataCommentTagFactory.go +26 -11
  70. package/native/core/factories/factory_utility_coverage_test.go +896 -907
  71. package/native/core/factories/internal/metadata/MetadataHelper.go +5 -28
  72. package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +2 -2
  73. package/native/core/programmers/RandomProgrammer.go +5 -2
  74. package/native/core/schemas/metadata/MetadataCollection.go +47 -5
  75. package/native/transform/CallExpressionTransformer.go +167 -0
  76. package/package.json +3 -3
  77. package/src/http.ts +18 -4
  78. package/src/internal/_assertGuard.ts +13 -2
  79. package/src/internal/_isFormatIdnHostname.ts +5 -1
  80. package/src/internal/_isFormatTime.ts +19 -2
  81. package/src/internal/_randomArray.ts +42 -6
  82. package/src/internal/_randomFormatByte.ts +17 -12
  83. package/src/internal/_randomFormatHostname.ts +2 -2
  84. package/src/internal/_randomFormatIdnHostname.ts +8 -9
  85. package/src/internal/_randomFormatRegex.ts +4 -6
  86. package/src/internal/_randomFormatTime.ts +15 -10
  87. package/src/internal/private/__randomComposition.ts +24 -0
  88. package/src/json.ts +16 -4
  89. package/src/module.ts +56 -22
  90. package/src/notations.ts +16 -4
  91. package/src/plain.ts +12 -3
  92. package/src/protobuf.ts +16 -4
@@ -3,7 +3,6 @@ package main
3
3
  import (
4
4
  "bytes"
5
5
  "os"
6
- "os/exec"
7
6
  "path/filepath"
8
7
  "runtime"
9
8
  "sort"
@@ -11,16 +10,81 @@ import (
11
10
  "testing"
12
11
  )
13
12
 
13
+ // ttscTypiaTestTypecheck requires a fixture project to be free of TypeScript
14
+ // errors, which is what makes an `@ts-expect-error` in a fixture load-bearing.
15
+ //
16
+ // It runs the build command in no-emit mode with the rewrite disabled, so the
17
+ // only diagnostics it can report are the program's own. It used to shell out to
18
+ // `pnpm exec ttsc --noEmit -p tsconfig.json`, which reported nothing and exited
19
+ // 0 for a fixture under `.tmp-ttsc-typia-tests` — `const value: number = "bad"`
20
+ // passed — so every caller was asserting against an oracle that could not fail.
21
+ // `runBuild` is the same program these tests already drive, and
22
+ // build_reports_semantic_diagnostics_test.go pins that it surfaces semantic
23
+ // diagnostics as status 2.
14
24
  func ttscTypiaTestTypecheck(t *testing.T, project string) {
15
25
  t.Helper()
16
- pnpm, err := exec.LookPath("pnpm")
17
- if err != nil {
18
- t.Skip("pnpm executable not found")
26
+ out, errText, code := ttscTypiaTestCapture(func() int {
27
+ return runBuild([]string{
28
+ "--cwd", project,
29
+ "--tsconfig", "tsconfig.json",
30
+ "--noEmit",
31
+ "--rewrite-mode", "none",
32
+ })
33
+ })
34
+ if code != 0 {
35
+ t.Fatalf("fixture typecheck failed: code=%d\nstdout=%s\nstderr=%s", code, out, errText)
36
+ }
37
+ }
38
+
39
+ // ttscTypiaTestWriteFactoryStub installs a typia whose declaration file sits at
40
+ // the path the transformer's identity test accepts, so a fixture that also
41
+ // carries an ambient or augmenting `declare module "typia"` differs from a
42
+ // plain one only in that declaration.
43
+ func ttscTypiaTestWriteFactoryStub(t *testing.T, project string) {
44
+ t.Helper()
45
+ root := filepath.Join(project, "node_modules", "typia")
46
+ lib := filepath.Join(root, "lib")
47
+ if err := os.MkdirAll(lib, 0o755); err != nil {
48
+ t.Fatalf("mkdir typia stub: %v", err)
19
49
  }
20
- cmd := exec.Command(pnpm, "exec", "ttsc", "--noEmit", "-p", "tsconfig.json")
21
- cmd.Dir = project
22
- if output, err := cmd.CombinedOutput(); err != nil {
23
- t.Fatalf("fixture typecheck failed: %v\n%s", err, output)
50
+ files := map[string]string{
51
+ "package.json": `{
52
+ "name": "typia",
53
+ "version": "0.0.0-test",
54
+ "main": "./lib/module.js",
55
+ "types": "./lib/module.d.ts",
56
+ "exports": {
57
+ ".": {
58
+ "types": "./lib/module.d.ts",
59
+ "default": "./lib/module.js"
60
+ },
61
+ "./lib/transform": "./lib/transform.js"
62
+ },
63
+ "ttsc": {
64
+ "plugin": { "transform": "typia/lib/transform" }
65
+ }
66
+ }
67
+ `,
68
+ filepath.Join("lib", "module.d.ts"): `declare namespace typia {
69
+ function createAssert<T>(): (input: unknown) => T;
70
+ function createIs<T>(): (input: unknown) => input is T;
71
+ }
72
+ declare const typia: {
73
+ createAssert: typeof typia.createAssert;
74
+ createIs: typeof typia.createIs;
75
+ };
76
+ export default typia;
77
+ export declare function createAssert<T>(): (input: unknown) => T;
78
+ export declare function createIs<T>(): (input: unknown) => input is T;
79
+ `,
80
+ filepath.Join("lib", "module.js"): "exports.createAssert = () => () => undefined;\nexports.createIs = () => () => false;\n",
81
+ filepath.Join("lib", "transform.js"): "module.exports = {};\n",
82
+ filepath.Join("lib", "transform.d.ts"): "export {};\n",
83
+ }
84
+ for name, body := range files {
85
+ if err := os.WriteFile(filepath.Join(root, name), []byte(body), 0o644); err != nil {
86
+ t.Fatalf("write typia stub %s: %v", name, err)
87
+ }
24
88
  }
25
89
  }
26
90
 
@@ -61,14 +125,13 @@ func ttscTypiaTestCapture(run func() int) (string, string, int) {
61
125
  func ttscTypiaTestWriteCommonRuntimeStubs(t *testing.T, runtimeDir string) {
62
126
  t.Helper()
63
127
  files := map[string]string{
64
- "typia-stub.cjs": "module.exports = {};\n",
65
- "validate-report-stub.cjs": ttscTypiaTestValidateReportStub,
66
- "standard-schema-stub.cjs": ttscTypiaTestStandardSchemaStub,
67
- "assert-guard-stub.cjs": ttscTypiaTestAssertGuardStub,
68
- "functional-error-stub.cjs": ttscTypiaTestFunctionalErrorStub,
69
- "access-expression-stub.cjs": ttscTypiaTestAccessExpressionStub,
70
- "string-length-stub.cjs": ttscTypiaTestStringLengthStub,
71
- "notation-stub.cjs": ttscTypiaTestNotationStub,
128
+ "typia-stub.cjs": "module.exports = {};\n",
129
+ "validate-report-stub.cjs": ttscTypiaTestValidateReportStub,
130
+ "standard-schema-stub.cjs": ttscTypiaTestStandardSchemaStub,
131
+ "assert-guard-stub.cjs": ttscTypiaTestAssertGuardStub,
132
+ "functional-error-stub.cjs": ttscTypiaTestFunctionalErrorStub,
133
+ "access-expression-stub.cjs": ttscTypiaTestAccessExpressionStub,
134
+ "notation-stub.cjs": ttscTypiaTestNotationStub,
72
135
  "json-stringify-array-stub.cjs": ttscTypiaTestJsonStringifyArrayStub,
73
136
  "json-stringify-property-stub.cjs": ttscTypiaTestJsonStringifyPropertyStub,
74
137
  "json-stringify-element-stub.cjs": ttscTypiaTestJsonStringifyElementStub,
@@ -90,7 +153,6 @@ func ttscTypiaTestRewriteCommonJS(t *testing.T, js string) string {
90
153
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_assertGuard")`, `require("./assert-guard-stub.cjs")`)
91
154
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_functionalTypeGuardErrorFactory")`, `require("./functional-error-stub.cjs")`)
92
155
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_accessExpressionAsString")`, `require("./access-expression-stub.cjs")`)
93
- runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_stringLength")`, `require("./string-length-stub.cjs")`)
94
156
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyArray")`, `require("./json-stringify-array-stub.cjs")`)
95
157
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyProperty")`, `require("./json-stringify-property-stub.cjs")`)
96
158
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyElement")`, `require("./json-stringify-element-stub.cjs")`)
@@ -160,9 +222,20 @@ const ttscTypiaTestValidateReportStub = `module.exports._validateReport = (array
160
222
  const ttscTypiaTestStandardSchemaStub = `module.exports._createStandardSchema = (validate) => validate;
161
223
  `
162
224
 
225
+ // A double for packages/typia/src/internal/_assertGuard.ts that takes the same
226
+ // branches: `exceptionable === true` and a callable-factory requirement. The
227
+ // generated function's second parameter is caller-supplied, so a pointwise
228
+ // hand-off (`rows.map(assertUser)`) fills it with the element index; testing
229
+ // truthiness here would let this stub report `factory is not a function` for a
230
+ // case the shipped helper handles. The fallback error is deliberately not a
231
+ // TypeGuardError — a stub cannot import typia — so cases assert `props`
232
+ // members rather than the shipped message format.
163
233
  const ttscTypiaTestAssertGuardStub = `module.exports._assertGuard = (exceptionable, props, factory) => {
164
- if (exceptionable) {
165
- const error = factory ? factory(props) : Object.assign(new Error(props.expected), props);
234
+ if (exceptionable === true) {
235
+ const error =
236
+ typeof factory === "function"
237
+ ? factory(props)
238
+ : Object.assign(new Error(props.expected), props);
166
239
  throw error;
167
240
  }
168
241
  return false;
@@ -217,13 +290,6 @@ const ttscTypiaTestRandomStringStub = `module.exports._randomString = (props) =>
217
290
  };
218
291
  `
219
292
 
220
- const ttscTypiaTestStringLengthStub = `module.exports._stringLength = (value) => {
221
- let count = 0;
222
- for (const _ of value) ++count;
223
- return count;
224
- };
225
- `
226
-
227
293
  const ttscTypiaTestAccessExpressionStub = `const reserved = new Set([
228
294
  "break",
229
295
  "case",
@@ -45,7 +45,7 @@ var FormatCheatSheet = map[string]string{
45
45
  "email": "/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test($input)",
46
46
  "hostname": "/^(?=.{1,253}\\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\\.?$/i.test($input)",
47
47
  "idn-email": "/^(([^<>()[\\]\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i.test($input)",
48
- "idn-hostname": "/^([a-z0-9\\u00a1-\\uffff0-9]+(-[a-z0-9\\u00a1-\\uffff0-9]+)*\\.)+[a-z\\u00a1-\\uffff]{2,}$/i.test($input)",
48
+ "idn-hostname": "/^(?=.{1,253}\\.?$)[a-z0-9\\u00a1-\\uffff](?:[a-z0-9\\u00a1-\\uffff-]{0,61}[a-z0-9\\u00a1-\\uffff])?(?:\\.[a-z0-9\\u00a1-\\uffff](?:[a-z0-9\\u00a1-\\uffff-]{0,61}[a-z0-9\\u00a1-\\uffff])?)*\\.?$/i.test($input)",
49
49
  "iri": `(() => !/[\u0000-\u0020\u007f-\u009f\ud800-\udfff"<>\\^\x60{|}]/u.test($input) && !/%(?![0-9A-Fa-f]{2})/u.test($input) && /^[A-Za-z][A-Za-z0-9+.-]*:/u.test($input))()`,
50
50
  "iri-reference": `(() => { if (/[\u0000-\u0020\u007f-\u009f\ud800-\udfff"<>\\^\x60{|}]/u.test($input) || /%(?![0-9A-Fa-f]{2})/u.test($input)) return false; const colon = $input.indexOf(":"); const boundary = $input.search(/[/?#]/u); return colon === -1 || (boundary !== -1 && boundary < colon) || /^[A-Za-z][A-Za-z0-9+.-]*:/u.test($input); })()`,
51
51
  "ipv4": "/^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/.test($input)",
@@ -56,7 +56,7 @@ var FormatCheatSheet = map[string]string{
56
56
  "url": "/^(?:https?|ftp):\\/\\/(?:[^\\s/?#@]+(?::[^\\s/?#@]*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?=.{1,253}(?::\\d{2,5})?(?:\\/[^\\s]*)?$)(?:[a-z0-9\\u00a1-\\uffff](?:[-a-z0-9\\u00a1-\\uffff]{0,61}[a-z0-9\\u00a1-\\uffff])?\\.)+(?:[a-z\\u00a1-\\uffff](?:[-a-z0-9\\u00a1-\\uffff]{0,61}[a-z0-9\\u00a1-\\uffff])))(?::\\d{2,5})?(?:\\/[^\\s]*)?$/iu.test($input)",
57
57
  "date-time": `(() => { const match = /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])[Tt]((?:[01][0-9]|2[0-3])):([0-5][0-9]):([0-5][0-9]|60)(?:\.[0-9]+)?(?:[Zz]|([+-])((?:[01][0-9]|2[0-3])):([0-5][0-9]))$/.exec($input); if (match === null) return false; const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); if (day > [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1] + (month === 2 && (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) ? 1 : 0)) return false; if (match[6] !== "60") return true; const instant = new Date(0); instant.setUTCFullYear(year, month - 1, day); instant.setUTCHours(Number(match[4]), Number(match[5]), 0, 0); const offset = match[7] === undefined ? 0 : (match[7] === "+" ? 1 : -1) * (Number(match[8]) * 60 + Number(match[9])); instant.setUTCMinutes(instant.getUTCMinutes() - offset); return instant.getUTCHours() === 23 && instant.getUTCMinutes() === 59 && ((instant.getUTCMonth() === 5 && instant.getUTCDate() === 30) || (instant.getUTCMonth() === 11 && instant.getUTCDate() === 31)); })()`,
58
58
  "date": `(() => { const match = /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/.exec($input); if (match === null) return false; const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); return day <= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1] + (month === 2 && (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) ? 1 : 0); })()`,
59
- "time": "/^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$/i.test($input)",
59
+ "time": `(() => { const match = /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(?:\.[0-9]+)?(?:[Zz]|([+-])((?:[01][0-9]|2[0-3])):([0-5][0-9]))$/.exec($input); if (match === null) return false; if (match[3] !== "60") return true; const offset = match[4] === undefined ? 0 : (match[4] === "+" ? 1 : -1) * (Number(match[5]) * 60 + Number(match[6])); const minutes = Number(match[1]) * 60 + Number(match[2]) - offset; return ((minutes % 1440) + 1440) % 1440 === 1439; })()`,
60
60
  "duration": "/^P(?!$)((\\d+Y)?(\\d+M)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+S)?)?|(\\d+W)?)$/.test($input)",
61
61
  "json-pointer": "/^(?:\\/(?:[^~/]|~0|~1)*)*$/.test($input)",
62
62
  "relative-json-pointer": "/^(?:0|[1-9][0-9]*)(?:#|(?:\\/(?:[^~/]|~0|~1)*)*)$/.test($input)",
@@ -268,7 +268,7 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
268
268
  Report func(msg string) any
269
269
  Value string
270
270
  }) metadataCommentTagFactory_TagRecord {
271
- return metadataCommentTagFactory_numeric(props, "MultipleOf", "multipleOf", "$importInternal(\"_isMultipleOf\")($input, "+props.Value+")", "$input % "+props.Value+"n === 0n")
271
+ return metadataCommentTagFactory_numeric(props, "MultipleOf", "multipleOf", "$input % "+props.Value+" === 0", "$input % "+props.Value+"n === 0n")
272
272
  },
273
273
  "format": func(props struct {
274
274
  Report func(msg string) any
@@ -292,8 +292,8 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
292
292
  }) metadataCommentTagFactory_TagRecord {
293
293
  value := metadataCommentTagFactory_parse_number(props)
294
294
  return metadataCommentTagFactory_TagRecord{"string": {
295
- {Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: props.Value + " <= $importInternal(\"_stringLength\")($input)", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}},
296
- {Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLength\")($input) <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}},
295
+ {Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: props.Value + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}},
296
+ {Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$input.length <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}},
297
297
  }}
298
298
  },
299
299
  "minLength": func(props struct {
@@ -301,14 +301,14 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
301
301
  Value string
302
302
  }) metadataCommentTagFactory_TagRecord {
303
303
  value := metadataCommentTagFactory_parse_number(props)
304
- return metadataCommentTagFactory_TagRecord{"string": {{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: props.Value + " <= $importInternal(\"_stringLength\")($input)", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}}}}
304
+ return metadataCommentTagFactory_TagRecord{"string": {{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: props.Value + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}}}}
305
305
  },
306
306
  "maxLength": func(props struct {
307
307
  Report func(msg string) any
308
308
  Value string
309
309
  }) metadataCommentTagFactory_TagRecord {
310
310
  value := metadataCommentTagFactory_parse_number(props)
311
- return metadataCommentTagFactory_TagRecord{"string": {{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLength\")($input) <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}}}}
311
+ return metadataCommentTagFactory_TagRecord{"string": {{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$input.length <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}}}}
312
312
  },
313
313
  }
314
314
 
@@ -407,13 +407,28 @@ func metadataCommentTagFactory_parse_type(props struct {
407
407
  "number": {{Name: "Type<" + strconv.Quote(value) + ">", Target: "number", Kind: "type", Value: value, Validate: validate, Exclusive: metadataCommentTagFactory_exclusive("type"), Schema: numberSchema}},
408
408
  }
409
409
  if value == "int64" || value == "uint64" {
410
- // The bigint form used to emit `true` for int64 and a lower bound only for
411
- // uint64, so `bigint & Type<"int64">` -- the spelling the documentation
412
- // recommends -- certified any magnitude at all. Both now delegate to the
413
- // helper that holds the exact inclusive bound a bigint can represent.
414
- bigintValidate := "$importInternal(\"isTypeUint64Bigint\")($input)"
410
+ // Both checks stay inline, spelled exactly as `Type<"int64">` and
411
+ // `Type<"uint64">` declare them, because `@type int64` and
412
+ // `bigint & Type<"int64">` are two spellings of one constraint.
413
+ //
414
+ // That declaration must not name a runtime helper the way the `number` arms
415
+ // above do. A `$importInternal(...)` in a tag template makes the emitted
416
+ // validator import a `typia/lib/internal/*` module, and the declaration
417
+ // lives in `@typia/interface`, which `typia` depends on through a caret
418
+ // range that only floats upward -- so an older `typia` installs a newer
419
+ // `@typia/interface` and emits an import its own runtime never shipped
420
+ // (#2330). `isTypeInt64` and `isTypeUint64` are safe there because
421
+ // `@typia/interface` 13.0.0 already named them and `typia` 13.0.0 already
422
+ // shipped them; a helper introduced later is not, and inside one major
423
+ // there is no range that prevents the pairing.
424
+ //
425
+ // The bound this leaves unenforced is real: int64 accepts any magnitude and
426
+ // uint64 only rejects negatives. #2338 owns restoring it, and only a major
427
+ // can carry it -- an inline exact comparison would name no helper, but
428
+ // tightening an accepted range rejects data that passes today.
429
+ bigintValidate := "BigInt(0) <= $input"
415
430
  if value == "int64" {
416
- bigintValidate = "$importInternal(\"isTypeInt64Bigint\")($input)"
431
+ bigintValidate = "true"
417
432
  }
418
433
  record["bigint"] = []schemametadata.IMetadataTypeTag{
419
434
  {Name: "Type<" + strconv.Quote(value) + ">", Target: "bigint", Kind: "type", Value: value, Validate: bigintValidate, Exclusive: metadataCommentTagFactory_exclusive("type"), Schema: bigintSchema},