fix(typia): tune random default lengths#1982
Merged
Merged
Conversation
Owner
Author
|
Follow-up after CI: the first run exposed an oversized recursive ArrayRecursive SDK payload. I kept the |
Owner
Author
|
Follow-up for recursive random arrays with positive
Local validation:
CI: all current PR checks pass except |
RandomJoiner.RequiresRecursiveArrayGuard (the single-argument wrapper) had no callers in production or tests; the decode path uses the RecursiveArrayGuardProps-based ...For variant exclusively. Remove the dead wrapper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_randomArray already imports OpenApi as a type; align _randomString, which references OpenApi only in a type position. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pin the _randomString length arithmetic: the unconstrained 5..10 span, a MaxLength below the default collapsing to exactly the cap, a lone MinLength keeping the +5 span, and a MinLength/MaxLength pair. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercise the oneOf expansion in randomProgrammer_array_schema_list for a recursive array whose element is `Self | string`, asserting the depth guard caps the self-referential branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a MapRecursiveKey @typia/template structure whose recursion travels through a `Map<Self, number>` key. The shared metadata recursion marker now follows map keys, but only the random feature exercised that path; feeding the structure into the generator matrix runs is/assert/validate/ random (plus standard-schema validate) and their spoilers against it, so the cross-feature codegen for a recursive map key is locked in. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pin the non-recursive _randomArray length arithmetic, mirroring the string-length test: the unconstrained 1..6 span, a MaxItems that caps only the maximum while the minimum stays 1 (MaxItems<8> stays 1..8), a lone MinItems keeping the +5 span, and a MinItems/MaxItems pair. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rator The random programmer now passes `recursive: true` to the array generator for arrays on a recursive type's cycle, and custom generators key off it to keep graph-shaped data finite. Document the field on both IRandomGenerator and IRandomGenerator.CustomMap so the contract is discoverable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
typia.random walked some recursive types until the stack overflowed at
runtime: a required, non-nullable object edge back to itself (e.g.
`interface A { self: A }`), a mutual object cycle, or a recursive tuple
rest element. These have no escape the depth cutoff can take — an
array/set/map empties, a nullable edge becomes null, an optional or
index-signature property drops out, or a union picks a finite variant —
so no finite value exists for the generator to build.
Add a least-fixpoint terminability analysis (a schema terminates if ANY
union option does; an object if ALL required literal properties do) and
reject an unsatisfiable recursive object or tuple at compile time through
the transform-diagnostic path, mirroring the existing recursive-MinItems
rejection. Types with any escape — including unions where only one variant
is finite and index-signature trees — keep generating as before.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… types Explain that recursion terminates only through an escape the depth cutoff can take (empty container, nullable, optional, index signature, or a finite union variant), and that a valveless recursive cycle is rejected at compile time with the satisfiable alternatives. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A `...X[]` tuple rest used to generate exactly one `X`, never a real spread, so `[number, ...string[]]` produced `[number, oneString]` and a recursive rest `[string, ...T[]]` recursed forever. Route the rest through the array helper so it spreads a possibly-empty array: it now emits zero or more elements, and when the element is the recursive owner the spread carries the `recursive` depth cutoff and empties at the limit. This makes recursive rest tuples terminate, so they are no longer caught by the unsatisfiable-recursion check; drop that diagnostic case and cover the spread (non-recursive and recursive) with a runtime test. Valveless object cycles stay rejected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The recursive depth cutoff (`5 >= _depth ? ... : []`) on a tuple rest
spread referenced `_depth`, which only exists inside a generated helper.
A top-level tuple whose element recurses through its own helper —
`typia.random<[string, ...INode[]]>()` with `interface INode { children:
INode[] }` — is inlined with no `_depth` binding, so the spread threw
`ReferenceError: _depth is not defined`. Emit the cutoff only when the
surrounding function exposes `_depth`; the element's own helper already
terminates the recursion otherwise. Cover the top-level case in the rest
runtime test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the recursive-termination test with `Set<Self>`, `Map<Self, V>`, and `Map<K, Self>` escapes so the container-empties-at-cutoff path is pinned for sets and for both map sides, not just arrays. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The unsatisfiable-recursion check ran a fresh reachability collect and terminability fixpoint for every recursive object and tuple. Since the metadata collection already enumerates every reachable object and tuple, replace the per-type IsUnsatisfiableRecursive* helpers (and their collect DFS) with a single UnsatisfiableRecursives pass over the whole collection, computed once in each function writer. Same rejections, fewer passes, ~60 fewer lines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use the en-us spellings `recognize` and `stabilizes` in the random recursion comments, and allow the Go `typ` identifier — a deliberate idiom the native tree uses because `type` is a reserved word — in typos.toml so the spell-check workflow passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
5..101..6, while recursive array props keep a zero-length default pathrecursive: truethroughIRandomGenerator.arrayprops when the array element graph is recursivecreateTtscPluginas a named export as well as defaultTests
pnpm --filter ./tests/test-typia-schema start -- --include random_defaultspnpm test:gopnpm formatpnpm --dir website buildgit diff --cached --check