diff --git a/package-lock.json b/package-lock.json index 33b78937..dbbb1d14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ts-pattern", - "version": "5.6.0", + "version": "5.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ts-pattern", - "version": "5.6.0", + "version": "5.6.1", "license": "MIT", "devDependencies": { "@types/jest": "^29.5.2", diff --git a/package.json b/package.json index 2dddb694..e6041a59 100644 --- a/package.json +++ b/package.json @@ -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", @@ -78,4 +78,4 @@ "ts-jest": "^29.1.2", "typescript": "^5.7.2" } -} \ No newline at end of file +} diff --git a/src/is-matching.ts b/src/is-matching.ts index f786ff1e..c9c99c0e 100644 --- a/src/is-matching.ts +++ b/src/is-matching.ts @@ -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'; @@ -33,10 +38,10 @@ export function isMatching>( * return input.name * } */ -export function isMatching>>( - pattern: P, - value: T -): value is P.infer

; +export function isMatching< + const T, + const P extends P.Pattern & UnknownProperties +>(pattern: P, value: T): value is P.infer

; export function isMatching>( ...args: [pattern: p, value?: any] diff --git a/src/types/Pattern.ts b/src/types/Pattern.ts index 6fecf1fa..3ac4deae 100644 --- a/src/types/Pattern.ts +++ b/src/types/Pattern.ts @@ -126,11 +126,13 @@ export interface Override { [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; diff --git a/tests/is-matching.test.ts b/tests/is-matching.test.ts index 882abca3..58f80501 100644 --- a/tests/is-matching.test.ts +++ b/tests/is-matching.test.ts @@ -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>; + } + }); + + 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>; + } + }); });