Skip to content

Commit

Permalink
isMatching: improve narrowing
Browse files Browse the repository at this point in the history
  • Loading branch information
gvergnaud committed Feb 22, 2025
1 parent 4d6c39b commit f1af270
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/is-matching.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MatchedValue, Pattern, UnknownProperties } from './types/Pattern';
import * as P from './patterns';
import { matchPattern } from './internals/helpers';
import { WithDefault } from './types/helpers';

/**
* This constraint allows using additional properties
Expand Down Expand Up @@ -47,7 +48,7 @@ export function isMatching<const p extends Pattern<unknown>>(
export function isMatching<const T, const P extends PatternConstraint<T>>(
pattern: P,
value: T
): value is P.infer<P>;
): value is T & WithDefault<P.narrow<T, P>, P.infer<P>>;

export function isMatching<const p extends Pattern<any>>(
...args: [pattern: p, value?: any]
Expand Down
2 changes: 1 addition & 1 deletion src/patterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export type infer<pattern> = InvertPattern<NoInfer<pattern>, unknown>;
* type Narrowed = P.narrow<Input, typeof Pattern>
* // ^? ['a', 'a' | 'b']
*/
export type narrow<input, pattern extends Pattern<any>> = ExtractPreciseValue<
export type narrow<input, pattern> = ExtractPreciseValue<
input,
InvertPattern<pattern, input>
>;
Expand Down
4 changes: 3 additions & 1 deletion tests/is-matching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ describe('isMatching', () => {
expect(isMatching({ topping: 'cheese' }, food)).toBe(true);

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

Expand Down
10 changes: 4 additions & 6 deletions tests/objects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,17 @@ describe('Objects', () => {
it('should work with symbols', () => {
const fn1 = (obj: Input) => {
if (isMatching({ [symbolA]: { [symbolB]: 'foo' } }, obj)) {
type t = Expect<
Equal<typeof obj, { [symbolA]: { [symbolB]: 'foo' } }>
>;
const value = obj[symbolA][symbolB];
type t = Expect<Equal<typeof value, 'foo'>>;
} else {
throw new Error('Expected obj to match the foo pattern!');
}
};

const fn2 = (obj: Input) => {
if (isMatching({ [symbolA]: { [symbolB]: 'bar' } }, obj)) {
type t = Expect<
Equal<typeof obj, { [symbolA]: { [symbolB]: 'bar' } }>
>;
const value = obj[symbolA][symbolB];
type t = Expect<Equal<typeof value, 'bar'>>;
throw new Error('Expected obj to not match the bar pattern!');
}
};
Expand Down

0 comments on commit f1af270

Please sign in to comment.