Skip to content

fix(typia): validate intersected object unions#1909

Open
samchon wants to merge 13 commits into
masterfrom
fix/1590-intersection-union-validation
Open

fix(typia): validate intersected object unions#1909
samchon wants to merge 13 commits into
masterfrom
fix/1590-intersection-union-validation

Conversation

@samchon

@samchon samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Intent

Fix #1590 by making the native transform validate intersected object unions without selecting an overlapping branch from one side of the intersection as if it proved the other side.

Changes

  • Tighten object-union specialization so shared or overlapping structural fields are not used as unsafe discriminators.
  • Keep safe shared literal discriminators usable with the Neighbor flag.
  • Make metadata containment/intersection checks handle Map keys/values, tuple elements, tuple rest wrappers and rest tails, empty tuple targets, nested collection entries, template literals, wrapper/native names, and overlapping collection buckets precisely enough for union specialization.
  • Share the runtime atomic-like native decision between metadata containment and native predicate generation, with BigInt explicitly excluded from that runtime-wrapper set.
  • Add transform/runtime coverage for the original Party & PartyRoleInfo case across is, validate, assert, and direct typia.validate paths.
  • Add focused Go regression tests for primitive-wrapper natives, collection buckets, native names, templates, tuple entries, tuple rest/empty targets, nested collection entries, map entries, object-valued shared fields, repeated tuple coverage, and neighbor discriminator behavior.
  • Bump typia to 13.0.0-dev.20260605.11 because this PR changes native source shipped in the npm package.

Validation

  • pnpm format
  • git diff --check
  • go test ./metadata/schema -run 'TestMetadataSchema(CoversNestedCollectionEntries|CoversTupleEntries|CoversMapEntries|CoversAtomicLikeNatives|IntersectsAtomicLikeNatives)$' -count=1 -v from packages/typia/test
  • go test ./metadata/schema -run 'TestMetadataSchema(CoversTupleEntries|Covers|Intersects)' -count=1 -v from packages/typia/test
  • go test ./helpers/predicator -run 'TestAtomicPredicator(RejectsNativeOverlaps|RecognizesPrimitiveNativeNames)$' -count=1 -v from packages/typia/test
  • go test ./core/programmers/internal ./core/programmers/json ./core/programmers/iterate -count=1 from packages/typia/native
  • go test ./core/schemas/metadata ./core/programmers/iterate -count=1 from packages/typia/native
  • go test ./core/programmers/helpers -run 'TestUnionPredicator(SkipsAtomicLikeNativeFields|ChecksNeighborFlag|SkipsSharedTemplateFields)$' -count=1 -v from packages/typia/native
  • go test ./core/programmers/helpers -run 'TestUnionPredicator(SkipsSharedObjectFields|SkipsSharedNativeNames|SkipsCollectionBucketFields|ChecksNeighborFlag)$' -count=1 -v from packages/typia/native
  • go test ./cmd/ttsc-typia -run TestIntersectionUnionValidationTransform -count=1 -v from packages/typia/native
  • pnpm test:go

Local Limitations

  • Local pnpm test is blocked on Node v22.15.0 before this PR's tests run because local ttsc resolves typia/lib/transform to packages/typia/src/transform.ts, which this Node version cannot require directly. GitHub CI uses Node 24.x.
  • Direct go test -tags typia_native_internal ./... from packages/typia/test is still blocked by existing package-layout/internal-import constraints outside this PR.

Remaining Gates

  • Research Review Round 13 after commit 27cb467cf.
  • GitHub CI after the latest push.

Fixes #1590.

@samchon

samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 1 produced surviving proposals. Applied follow-up commit b805844 to split native-name metadata tests, add direct UnionPredicator coverage for shared native fields, harden the transform runtime fixture/import guards, and expand the valid/invalid intersection matrix. Local Go validation has been rerun after the follow-up.

@samchon

samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 2 produced surviving proposals. Applied follow-up commit 19e4042 to mirror reserved-word handling in the shared transform runtime stub and remove #1590 from .wiki before final issue closure. Local validation was rerun after the follow-up: pnpm format, focused transform/metadata/UnionPredicator tests, pnpm test:go, diff checks, and .wiki no-match search.

@samchon

samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 3 produced one surviving proposal. Applied follow-up commit 588e02f to rename the shared transform helper file to *_test.go so it is listed under TestGoFiles, not production GoFiles. Verified with go list, focused transform tests, UnionPredicator test, pnpm run format:go, pnpm test:go, diff checks, and .wiki no-match search.

@samchon

samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 4 follow-up applied in ee7926abb:

  • mirrored _validateReport path filtering/default-description behavior in the native transform test stub;
  • kept transform_helpers_test.go test-only and verified it with go list -json ./cmd/ttsc-typia;
  • added primitive-wrapper native overlap/coverage for String, Number, and Boolean against matching primitives/constants/template strings;
  • added Set/Map bucket overlap and explicit Map key/value coverage;
  • added focused metadata and UnionPredicator regression tests for those cases;
  • corrected the PR body wording for the go test -tags typia_native_internal ./... limitation.

Local validation already passed before the push: pnpm format, pnpm run format:go, focused Go tests, pnpm test:go, full go test ./... -count=1 under both packages/typia/native and packages/typia/test, and .wiki grep for #1590.

@samchon

samchon commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 5 follow-up applied in 8a78fe660:

  • added conservative template-vs-template intersection handling and metadata coverage;
  • added array/tuple cross-bucket intersection handling and metadata/UnionPredicator coverage;
  • added transform runtime cases for primitive-wrapper shared fields, empty Set, empty Map, and array/tuple branch selection;
  • added negative template coverage checks for MetadataSchema_covers;
  • corrected the PR body to remove the stale .wiki removal claim.

Focused validation after the patch passed: pnpm format, metadata schema tests, UnionPredicator tests, TestIntersectionUnionValidationTransform, and git diff --check.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

Research Review Round 6 follow-up applied in 4f31af7fb:

  • made template/string-literal intersections conservative so a literal like id-1 can no longer be selected as a discriminator against `id-${number}`;
  • tightened the template intersection test to use an actually overlapping non-identical pair instead of pinning a disjoint pair;
  • added direct template coverage tests for atomic string and exact template matches;
  • strengthened UnionPredicator helper assertions to verify Index, Object, selected property ownership, and Neighbor flags.

Focused validation passed after the patch: pnpm format, metadata template tests, UnionPredicator shared-discriminator tests, TestIntersectionUnionValidationTransform, and git diff --check.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

Round 7 follow-up pushed in 9a15ad5. I kept the transform runtime Date regression focused on rejection across is/validate/assert/direct validate, moved template-only negative coverage into the template containment test, added direct Neighbor=true discriminator coverage, added non-identical template overlap coverage, and fixed tuple element containment with tuple/map regression tests. Focused Go validations and pnpm format passed locally.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

Round 8 follow-up pushed in 5e86978. I fixed nested collection coverage by removing the top-level-only array/tuple coverage gap with a visited-pair guard, added nested array/tuple regression tests, widened the transform test comment to match its runtime guard scope, and shared the runtime atomic-like native decision between metadata containment and Check_native while explicitly keeping BigInt out of that runtime-wrapper set. Validation passed locally: pnpm format, focused metadata/helper/transform Go tests, and pnpm test:go.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

RRR 9 follow-up pushed as 2fff250d0.

Applied validated findings:

  • Made MetadataSchema_covers keep strict root identity semantics while allowing nested same-pointer comparisons, and made the visited-pair guard path-local so one failed branch cannot leak into sibling candidates.
  • Split runtime atomic/native filtering from schema primitive routing. Runtime validation/stringify now suppresses only actual Boolean/Number/String object-wrapper overlaps and leaves bigint behavior intact; schema-side routing still treats BigInt as an atomic-like native where needed.
  • Reused the canonical MetadataSchema_atomicLikeNative mapping in native predicate generation instead of lowering arbitrary native names at the callsite.
  • Added invalid right-branch runtime cases for shared Date, Uint8Array, primitive-wrapper, Set, Map, and array/tuple fields.
  • Added focused regressions for duplicate nested array candidates, reused tuple element pointers, runtime BigInt preservation, and case-insensitive runtime predicate comparison.

Local validation after the push:

  • pnpm format
  • git diff --check
  • go test ./cmd/ttsc-typia -run TestIntersectionUnionValidationTransform -count=1 -v
  • go test ./helpers/predicator -run TestAtomicPredicator(RejectsNativeOverlaps|RecognizesPrimitiveNativeNames)$ -count=1 -v
  • go test ./core/programmers/internal ./core/programmers/json ./core/programmers/iterate -count=1
  • pnpm test:go

Next gate: RRR 10 on 2fff250d0, then latest GitHub CI.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

RRR 10 follow-up pushed as 570def449.

Applied validated findings:

  • Fixed repeated-extra tuple containment indexing in MetadataSchema_covers; the old i-len(target) index could panic when the source tuple had more than one repeated extra element.
  • Added a tuple regression for multiple repeated extra elements.
  • Added UnionPredicator coverage proving shared object-valued properties are not selected as discriminators.
  • Tightened shared Set, Map, and array/tuple runtime invalid cases so the value is left-shaped while the right branch is selected, proving the right branch still validates the shared property.

Rejected finding:

  • Plain gofmt -l is not the repository formatter gate here. pnpm format / pnpm run format:go intentionally run gofmt and then convert Go tabs to two spaces; this was rerun and passed.

Local validation after the push:

  • pnpm format
  • git diff --check
  • go test ./metadata/schema -run TestMetadataSchemaCoversTupleEntries -count=1 -v
  • go test ./core/programmers/helpers -run TestUnionPredicator(SkipsSharedObjectFields|SkipsSharedNativeNames|SkipsCollectionBucketFields|ChecksNeighborFlag)$ -count=1 -v
  • go test ./cmd/ttsc-typia -run TestIntersectionUnionValidationTransform -count=1 -v
  • pnpm test:go

Next gate: RRR 11 on 570def449, then latest GitHub CI.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

RRR 11 follow-up pushed as 6c6545e03.

Applied validated findings:

  • Added isParty(invalidOtherMissingDetail) negative coverage so the original invalid other branch is checked through createIs as well as validate, direct typia.validate, and assert.
  • Closed MetadataSchema_covers fallthroughs for empty tuple targets and target Rest wrappers.
  • Added tuple coverage for empty targets, rest-only source tuples, mismatched rest targets, compatible rest targets, and Rest targets that also carry another bucket.

Rejected finding:

  • Plain gofmt -l remains rejected as a standalone gate because repo formatting is pnpm format / pnpm run format:go, which intentionally applies the local Go formatting convention after gofmt.

Local validation after the push:

  • pnpm format
  • git diff --check
  • go test ./metadata/schema -run TestMetadataSchema(CoversTupleEntries|Covers|Intersects) -count=1 -v
  • go test ./cmd/ttsc-typia -run TestIntersectionUnionValidationTransform -count=1 -v
  • pnpm test:go

Next gate: RRR 12 on 6c6545e03, then latest GitHub CI.

@samchon

samchon commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

RRR 12 follow-up pushed as 27cb467cf.

Applied validated findings:

  • Added BigInt primitive coverage for createIs and createAssert, alongside the existing createValidate checks. The coverage intentionally asserts primitive 1n only, not Object(1n).
  • Fixed source trailing-rest tuple coverage so tuples like [string, ...number[]] can cover fixed target tails such as [head, 1, 2].
  • Added tuple coverage for source rest-only tuples covering non-empty fixed targets and for mismatched source rest tails.

Local validation after the push:

  • pnpm format
  • git diff --check
  • go test ./metadata/schema -run TestMetadataSchema(CoversTupleEntries|Covers|Intersects) -count=1 -v
  • go test ./cmd/ttsc-typia -run TestIntersectionUnionValidationTransform -count=1 -v
  • go test ./core/programmers/internal ./core/programmers/json ./core/programmers/iterate -count=1
  • go test ./helpers/predicator -run TestAtomicPredicator(RejectsNativeOverlaps|RecognizesPrimitiveNativeNames)$ -count=1 -v
  • pnpm test:go

Next gate: RRR 13 on 27cb467cf, then latest GitHub CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Typia runtime validation fails on intersections of discriminated union types

1 participant