Skip to content

Commit 75e3967

Browse files
authored
Merge pull request #307 from gvergnaud/gvergnaud/fix-is-matching-non-objects
fix(isMatching): Fix non-object patterns
2 parents 1520b57 + 45695d1 commit 75e3967

File tree

4 files changed

+64
-14
lines changed

4 files changed

+64
-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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ts-pattern",
3-
"version": "5.6.1",
3+
"version": "5.6.2",
44
"description": " The exhaustive Pattern Matching library for TypeScript.",
55
"type": "module",
66
"source": "src/index.ts",

src/is-matching.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
import {
2-
MatchedValue,
3-
Pattern,
4-
UnknownPattern,
5-
UnknownProperties,
6-
} from './types/Pattern';
1+
import { MatchedValue, Pattern, UnknownProperties } from './types/Pattern';
72
import * as P from './patterns';
83
import { matchPattern } from './internals/helpers';
94

5+
/**
6+
* This constraint allows using additional properties
7+
* in object patterns. See "should allow targetting unknown properties"
8+
* unit test in `is-matching.test.ts`.
9+
*/
10+
type PatternConstraint<T> = T extends readonly any[]
11+
? P.Pattern<T>
12+
: T extends object
13+
? P.Pattern<T> & UnknownProperties
14+
: P.Pattern<T>;
15+
1016
/**
1117
* `isMatching` takes pattern and returns a **type guard** function, cheching if a value matches this pattern.
1218
*
@@ -38,10 +44,10 @@ export function isMatching<const p extends Pattern<unknown>>(
3844
* return input.name
3945
* }
4046
*/
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>;
47+
export function isMatching<const T, const P extends PatternConstraint<T>>(
48+
pattern: P,
49+
value: T
50+
): value is P.infer<P>;
4551

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

tests/is-matching.test.ts

+45-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe('isMatching', () => {
2727
);
2828
}
2929
});
30+
3031
it('should act as a type guard function if given a two arguments', () => {
3132
const something: unknown = {
3233
title: 'Hello',
@@ -56,6 +57,47 @@ describe('isMatching', () => {
5657
}
5758
});
5859

60+
it('should work with object patterns', () => {
61+
const value: unknown = { foo: true };
62+
expect(isMatching({ foo: true }, value)).toEqual(true);
63+
expect(isMatching({ foo: 'true' }, value)).toEqual(false);
64+
});
65+
66+
it('should work with array patterns', () => {
67+
const value: unknown = [1, 2, 3];
68+
expect(isMatching(P.array(P.number), value)).toEqual(true);
69+
expect(isMatching(P.array(P.string), value)).toEqual(false);
70+
});
71+
72+
it('should work with variadic patterns', () => {
73+
const value: unknown = [1, 2, 3];
74+
expect(isMatching([1, ...P.array(P.number)], value)).toEqual(true);
75+
expect(isMatching([2, ...P.array(P.number)], value)).toEqual(false);
76+
});
77+
78+
it('should work with primitive patterns', () => {
79+
const value: unknown = 1;
80+
expect(isMatching(P.number, value)).toEqual(true);
81+
expect(isMatching(P.boolean, value)).toEqual(false);
82+
});
83+
84+
it('should work with literal patterns', () => {
85+
const value: unknown = 1;
86+
expect(isMatching(1, value)).toEqual(true);
87+
expect(isMatching('oops', value)).toEqual(false);
88+
});
89+
90+
it('should work with union and intersection patterns', () => {
91+
const value: unknown = { foo: true };
92+
expect(isMatching(P.union({ foo: true }, { bar: false }), value)).toEqual(
93+
true
94+
);
95+
96+
expect(isMatching(P.union({ foo: false }, { bar: false }), value)).toEqual(
97+
false
98+
);
99+
});
100+
59101
type Pizza = { type: 'pizza'; topping: string };
60102
type Sandwich = { type: 'sandwich'; condiments: string[] };
61103
type Food = Pizza | Sandwich;
@@ -83,7 +125,9 @@ describe('isMatching', () => {
83125

84126
isMatching(
85127
// @ts-expect-error
86-
{ type: 'oops' },
128+
{
129+
type: 'oops',
130+
},
87131
food
88132
);
89133
});

0 commit comments

Comments
 (0)