Skip to content

Commit c415e0c

Browse files
authored
Merge pull request #305 from gvergnaud/gvergnaud/fix-is-matching-union
fix(isMatching): Allow unknown properties in pattern
2 parents 34f7a41 + 2be1c5c commit c415e0c

File tree

5 files changed

+38
-14
lines changed

5 files changed

+38
-14
lines changed

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ts-pattern",
3-
"version": "5.6.0",
3+
"version": "5.6.1",
44
"description": " The exhaustive Pattern Matching library for TypeScript.",
55
"type": "module",
66
"source": "src/index.ts",
@@ -78,4 +78,4 @@
7878
"ts-jest": "^29.1.2",
7979
"typescript": "^5.7.2"
8080
}
81-
}
81+
}

src/is-matching.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { MatchedValue, Pattern } from './types/Pattern';
1+
import {
2+
MatchedValue,
3+
Pattern,
4+
UnknownPattern,
5+
UnknownProperties,
6+
} from './types/Pattern';
27
import * as P from './patterns';
38
import { matchPattern } from './internals/helpers';
49

@@ -33,10 +38,10 @@ export function isMatching<const p extends Pattern<unknown>>(
3338
* return input.name
3439
* }
3540
*/
36-
export function isMatching<const T, const P extends P.Pattern<NoInfer<T>>>(
37-
pattern: P,
38-
value: T
39-
): value is P.infer<P>;
41+
export function isMatching<
42+
const T,
43+
const P extends P.Pattern<T> & UnknownProperties
44+
>(pattern: P, value: T): value is P.infer<P>;
4045

4146
export function isMatching<const p extends Pattern<any>>(
4247
...args: [pattern: p, value?: any]

src/types/Pattern.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,13 @@ export interface Override<a> {
126126
[symbols.override]: a;
127127
}
128128

129+
export type UnknownProperties = { readonly [k: PropertyKey]: unknown };
130+
129131
export type UnknownPattern =
130132
| readonly []
131133
| readonly [unknown, ...unknown[]]
132134
| readonly [...unknown[], unknown]
133-
| { readonly [k: string]: unknown }
135+
| UnknownProperties
134136
| Primitives
135137
| UnknownMatcher;
136138

tests/is-matching.test.ts

+21-4
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,28 @@ describe('isMatching', () => {
8282
const food = { type: 'pizza', topping: 'cheese' } as Food;
8383

8484
isMatching(
85-
{
86-
// @ts-expect-error
87-
type: 'oops',
88-
},
85+
// @ts-expect-error
86+
{ type: 'oops' },
8987
food
9088
);
9189
});
90+
91+
it('should allow patterns targetting one member of a union type', () => {
92+
const food = { type: 'pizza', topping: 'cheese' } as Food;
93+
expect(isMatching({ topping: 'cheese' }, food)).toBe(true);
94+
95+
if (isMatching({ topping: 'cheese' }, food)) {
96+
type t = Expect<Equal<typeof food, Food & { topping: 'cheese' }>>;
97+
}
98+
});
99+
100+
it('should allow targetting unknown properties', () => {
101+
const food = { type: 'pizza', topping: 'cheese' } as Food;
102+
103+
expect(isMatching({ unknownProp: P.instanceOf(Error) }, food)).toBe(false);
104+
105+
if (isMatching({ unknownProp: P.instanceOf(Error) }, food)) {
106+
type t = Expect<Equal<typeof food, Food & { unknownProp: Error }>>;
107+
}
108+
});
92109
});

0 commit comments

Comments
 (0)