🐛 Type partial W matcher without an any cast

getPrimitiveUnionMatcherPartialW was declared with the intended
P-inferring signature but assigned via `as any`, hiding that the
declared parameter was not assignable to the implementation's. The
union in PatternPrimitiveUnionPartial makes the `_` arm demand
`_ ∈ keyof P`, which the exhaustive arm cannot prove.

Intersect the inference hook Simplify<P> with the implementation's
parameter shape, R pinned to PatternReturns<P>, so the assignment
type-checks while callers keep inferring P from the argument.

Add a spec for the exhaustive (no `_`) pattern.
This commit is contained in:
tmu committed 2026-09-16 19:10:40 +00:00
1 parent 2ff67801e0
commit cce030b8e5
2 files changed
+27 -4

No files matched your search

+17
View File
@@ -170,3 +170,20 @@ test("getPrimitiveUnionMatcherPartialW allows gaps and widens to the union of ha
assert.equal(matcher("y"), "fallback");
assert.equal(matcher("z"), "fallback");
});
test("getPrimitiveUnionMatcherPartialW also accepts an exhaustive pattern", () => {
// Arrange
const factory = getPrimitiveUnionMatcherPartialW<"x" | "y">();
// Act
const matcher = factory({
x: () => 1 as const,
y: () => "two" as const,
});
// Assert
// ❌ ReturnsStrict: mixed handler returns widen to their union.
expectTypeOf(matcher).toEqualTypeOf<(shape: "x" | "y") => 1 | "two">();
assert.equal(matcher("x"), 1);
assert.equal(matcher("y"), "two");
});