Skip to content

Commit

Permalink
Merge pull request #305 from gvergnaud/gvergnaud/fix-is-matching-union
Browse files Browse the repository at this point in the history
fix(isMatching): Allow unknown properties in pattern
  • Loading branch information
gvergnaud authored Jan 19, 2025
2 parents 34f7a41 + 2be1c5c commit c415e0c
Show file tree
Hide file tree
Showing 5 changed files with 38 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.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-pattern",
"version": "5.6.0",
"version": "5.6.1",
"description": " The exhaustive Pattern Matching library for TypeScript.",
"type": "module",
"source": "src/index.ts",
Expand Down Expand Up @@ -78,4 +78,4 @@
"ts-jest": "^29.1.2",
"typescript": "^5.7.2"
}
}
}
15 changes: 10 additions & 5 deletions src/is-matching.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { MatchedValue, Pattern } from './types/Pattern';
import {
MatchedValue,
Pattern,
UnknownPattern,
UnknownProperties,
} from './types/Pattern';
import * as P from './patterns';
import { matchPattern } from './internals/helpers';

Expand Down Expand Up @@ -33,10 +38,10 @@ export function isMatching<const p extends Pattern<unknown>>(
* return input.name
* }
*/
export function isMatching<const T, const P extends P.Pattern<NoInfer<T>>>(
pattern: P,
value: T
): value is P.infer<P>;
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 p extends Pattern<any>>(
...args: [pattern: p, value?: any]
Expand Down
4 changes: 3 additions & 1 deletion src/types/Pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ export interface Override<a> {
[symbols.override]: a;
}

export type UnknownProperties = { readonly [k: PropertyKey]: unknown };

export type UnknownPattern =
| readonly []
| readonly [unknown, ...unknown[]]
| readonly [...unknown[], unknown]
| { readonly [k: string]: unknown }
| UnknownProperties
| Primitives
| UnknownMatcher;

Expand Down
25 changes: 21 additions & 4 deletions tests/is-matching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,28 @@ describe('isMatching', () => {
const food = { type: 'pizza', topping: 'cheese' } as Food;

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

it('should allow patterns targetting one member of a union type', () => {
const food = { type: 'pizza', topping: 'cheese' } as Food;
expect(isMatching({ topping: 'cheese' }, food)).toBe(true);

if (isMatching({ topping: 'cheese' }, food)) {
type t = Expect<Equal<typeof food, Food & { topping: 'cheese' }>>;
}
});

it('should allow targetting unknown properties', () => {
const food = { type: 'pizza', topping: 'cheese' } as Food;

expect(isMatching({ unknownProp: P.instanceOf(Error) }, food)).toBe(false);

if (isMatching({ unknownProp: P.instanceOf(Error) }, food)) {
type t = Expect<Equal<typeof food, Food & { unknownProp: Error }>>;
}
});
});

0 comments on commit c415e0c

Please sign in to comment.