diff --git a/ark/schema/__tests__/morphs.test.ts b/ark/schema/__tests__/morphs.test.ts index 102ba1a98..37de9893c 100644 --- a/ark/schema/__tests__/morphs.test.ts +++ b/ark/schema/__tests__/morphs.test.ts @@ -34,6 +34,16 @@ contextualize(() => { attest(n.rawOut.expression).snap("number") }) + it("unions declared morphs", () => { + const morph = (value: string) => value + const n = rootSchema([ + { declaredIn: intrinsic.string, morphs: morph }, + { declaredIn: intrinsic.string, morphs: morph } + ]) + + attest(n.rawIn.expression).equals("string") + }) + contextualize.each( "declared", () => { diff --git a/ark/schema/roots/union.ts b/ark/schema/roots/union.ts index 535a1449e..928448299 100644 --- a/ark/schema/roots/union.ts +++ b/ark/schema/roots/union.ts @@ -126,9 +126,13 @@ const implementation: nodeImplementationOf = const matchingMorph = branches[ matchingMorphIndex ] as Morph.Node + const mergedIn = + matchingMorph.inner.in && node.inner.in ? + matchingMorph.inner.in.rawOr(node.inner.in) + : matchingMorph.rawIn.rawOr(node.rawIn) branches[matchingMorphIndex] = ctx.$.node("morph", { ...matchingMorph.inner, - in: matchingMorph.rawIn.rawOr(node.rawIn) + in: mergedIn }) } } else branches.push(node) diff --git a/ark/type/__tests__/narrow.test.ts b/ark/type/__tests__/narrow.test.ts index e9c4cc0ab..513934260 100644 --- a/ark/type/__tests__/narrow.test.ts +++ b/ark/type/__tests__/narrow.test.ts @@ -261,4 +261,25 @@ contextualize(() => { attest(T.t).type.toString.snap("unknown") attest(T.json).snap({ predicate: ["$ark.unknownPredicate854"] }) }) + + it("preserves piped branch input narrows through an intersection", () => { + const PipedItem = type("string.numeric & string.numeric.parse").narrow( + (_data, ctx) => ctx.reject("always reject") + ) + const UnpipedItem = type("string").narrow((_data, ctx) => + ctx.reject("always reject") + ) + const Variant = type({ kind: "'a'", value: PipedItem }).or({ + kind: "'b'", + value: UnpipedItem + }) + const Meta = type({ code: type("string.numeric.parse") }).narrow(() => true) + const Thing = Variant.and(Meta) + + attest( + Thing({ kind: "a", code: "1", value: "1" }) + .toString() + .includes("always reject") + ).equals(true) + }) })