Skip to content

Commit

Permalink
Merge pull request #307 from gvergnaud/gvergnaud/fix-is-matching-non-…
Browse files Browse the repository at this point in the history
…objects

fix(isMatching): Fix non-object patterns
  • Loading branch information
gvergnaud authored Jan 21, 2025
2 parents 1520b57 + 45695d1 commit 75e3967
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 14 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-pattern",
"version": "5.6.1",
"version": "5.6.2",
"description": " The exhaustive Pattern Matching library for TypeScript.",
"type": "module",
"source": "src/index.ts",
Expand Down
26 changes: 16 additions & 10 deletions src/is-matching.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import {
MatchedValue,
Pattern,
UnknownPattern,
UnknownProperties,
} from './types/Pattern';
import { MatchedValue, Pattern, UnknownProperties } from './types/Pattern';
import * as P from './patterns';
import { matchPattern } from './internals/helpers';

/**
* This constraint allows using additional properties
* in object patterns. See "should allow targetting unknown properties"
* unit test in `is-matching.test.ts`.
*/
type PatternConstraint<T> = T extends readonly any[]
? P.Pattern<T>
: T extends object
? P.Pattern<T> & UnknownProperties
: P.Pattern<T>;

/**
* `isMatching` takes pattern and returns a **type guard** function, cheching if a value matches this pattern.
*
Expand Down Expand Up @@ -38,10 +44,10 @@ export function isMatching<const p extends Pattern<unknown>>(
* return input.name
* }
*/
export function isMatching<
const T,
const P extends P.Pattern<T> & UnknownProperties
>(pattern: P, value: T): value is P.infer<P>;
export function isMatching<const T, const P extends PatternConstraint<T>>(
pattern: P,
value: T
): value is P.infer<P>;

export function isMatching<const p extends Pattern<any>>(
...args: [pattern: p, value?: any]
Expand Down
46 changes: 45 additions & 1 deletion tests/is-matching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('isMatching', () => {
);
}
});

it('should act as a type guard function if given a two arguments', () => {
const something: unknown = {
title: 'Hello',
Expand Down Expand Up @@ -56,6 +57,47 @@ describe('isMatching', () => {
}
});

it('should work with object patterns', () => {
const value: unknown = { foo: true };
expect(isMatching({ foo: true }, value)).toEqual(true);
expect(isMatching({ foo: 'true' }, value)).toEqual(false);
});

it('should work with array patterns', () => {
const value: unknown = [1, 2, 3];
expect(isMatching(P.array(P.number), value)).toEqual(true);
expect(isMatching(P.array(P.string), value)).toEqual(false);
});

it('should work with variadic patterns', () => {
const value: unknown = [1, 2, 3];
expect(isMatching([1, ...P.array(P.number)], value)).toEqual(true);
expect(isMatching([2, ...P.array(P.number)], value)).toEqual(false);
});

it('should work with primitive patterns', () => {
const value: unknown = 1;
expect(isMatching(P.number, value)).toEqual(true);
expect(isMatching(P.boolean, value)).toEqual(false);
});

it('should work with literal patterns', () => {
const value: unknown = 1;
expect(isMatching(1, value)).toEqual(true);
expect(isMatching('oops', value)).toEqual(false);
});

it('should work with union and intersection patterns', () => {
const value: unknown = { foo: true };
expect(isMatching(P.union({ foo: true }, { bar: false }), value)).toEqual(
true
);

expect(isMatching(P.union({ foo: false }, { bar: false }), value)).toEqual(
false
);
});

type Pizza = { type: 'pizza'; topping: string };
type Sandwich = { type: 'sandwich'; condiments: string[] };
type Food = Pizza | Sandwich;
Expand Down Expand Up @@ -83,7 +125,9 @@ describe('isMatching', () => {

isMatching(
// @ts-expect-error
{ type: 'oops' },
{
type: 'oops',
},
food
);
});
Expand Down

0 comments on commit 75e3967

Please sign in to comment.