diff --git a/src/primitive.test.ts b/src/primitive.test.ts index e50e57e..382cda0 100644 --- a/src/primitive.test.ts +++ b/src/primitive.test.ts @@ -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"); +}); diff --git a/src/primitive.ts b/src/primitive.ts index 04d411b..9ecae69 100644 --- a/src/primitive.ts +++ b/src/primitive.ts @@ -55,7 +55,13 @@ export const getPrimitiveUnionMatcherPartial: () => < export const getPrimitiveUnionMatcherPartialW: < T extends string | number, >() =>

>( - pattern: Simplify

, - - // oxlint-disable-next-line typescript/no-explicit-any typescript/no-unsafe-type-assertion -) => UnaryFn> = getPrimitiveUnionMatcherPartial as any; + /* + `Simplify

` is the inference hook: callers infer `P` from the argument. + the second half pins the impl parameter's `R` to `PatternReturns

`. + that makes the `= getPrimitiveUnionMatcherPartial` assignment type-check. + neither half works alone. + without the witness the union's `_` arm demands `_ ∈ keyof P`. + without `Simplify

` the parameter types do not compare. + */ + pattern: Simplify

& PatternPrimitiveUnionPartial, T>, +) => UnaryFn> = getPrimitiveUnionMatcherPartial;