✨ Reject a fallback for an exhaustive map
A fallback paired with a handler map that already covers `T` was still accepted, even though its remainder is empty. Fold the guard into `Handled`'s own (F-bounded) constraint so it is checked after inference; a conditional in the fallback parameter is evaluated while `Handled` is still its constraint and rejects every partial map whose handler callbacks need contextual typing.
This commit is contained in:
1 parent
7e7f716424
commit
f27966e803
5 files changed
+65
-14
No files matched your search
@@ -309,6 +309,26 @@ test("getMatcher factory rejects patterns outside its contract", () => {
|
||||
factory({ a: () => 1 });
|
||||
// @ts-expect-error a `string` fallback does not fit the `number` handler
|
||||
factory({ a: () => 1 }, () => "x");
|
||||
// @ts-expect-error a fallback is redundant once the map covers the universe
|
||||
factory({ a: () => 1, b: () => 2 }, () => 0);
|
||||
});
|
||||
|
||||
test("getMatcher: an open universe keeps the fallback's remainder open", () => {
|
||||
// Arrange
|
||||
const factory = getMatcher<string>();
|
||||
|
||||
// Act
|
||||
const matcher = factory({ a: () => 1 }, (s) => {
|
||||
// The map's literal keys do not close an open universe, so the
|
||||
// remainder stays `string` and the fallback is not redundant.
|
||||
expectTypeOf(s).toEqualTypeOf<string>();
|
||||
return 2 as const;
|
||||
});
|
||||
|
||||
// Assert
|
||||
expectTypeOf(matcher).toEqualTypeOf<(shape: string) => number>();
|
||||
assert.equal(matcher("a"), 1);
|
||||
assert.equal(matcher("b"), 2);
|
||||
});
|
||||
|
||||
test("getMatcherW factory rejects patterns outside its contract", () => {
|
||||
@@ -324,6 +344,8 @@ test("getMatcherW factory rejects patterns outside its contract", () => {
|
||||
});
|
||||
// @ts-expect-error a gap without a `_` fallback is not exhaustive
|
||||
factory({ x: () => 1 as const });
|
||||
// @ts-expect-error a fallback is redundant once the map covers the universe
|
||||
factory({ x: () => 1 as const, y: () => 2 as const }, () => 0);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in new issue
Block a user