@@ -35,6 +35,8 @@ import {
3535 ArrayChainable ,
3636 Variadic ,
3737 ObjectChainable ,
38+ ObjectPattern ,
39+ EmptyObjectPattern ,
3840} from './types/Pattern' ;
3941
4042export type { Pattern , Fn as unstable_Fn } ;
@@ -156,6 +158,14 @@ function arrayChainable<pattern extends Matcher<any, any, any, any, any>>(
156158 } ) as any ;
157159}
158160
161+ function objectChainable < pattern extends Matcher < any , any , any , any , any > > (
162+ pattern : pattern
163+ ) : ObjectChainable < pattern > {
164+ return Object . assign ( chainable ( pattern ) , {
165+ empty : ( ) => emptyObject ,
166+ } ) as any ;
167+ }
168+
159169/**
160170 * `P.optional(subpattern)` takes a sub pattern and returns a pattern which matches if the
161171 * key is undefined or if it is defined and the sub pattern matches its value.
@@ -635,10 +645,15 @@ function isNullish<T>(x: T | null | undefined): x is null | undefined {
635645 return x === null || x === undefined ;
636646}
637647
638- function isObject < T > ( x : T | object ) : x is object {
639- return typeof x === 'object' &&
640- ! Array . isArray ( x ) &&
641- x !== null
648+ function isObject ( x : unknown ) : x is object {
649+ return ! ! x && ( typeof x === 'object' || typeof x === 'function' ) ;
650+ }
651+
652+ function isEmptyObject ( x : unknown ) {
653+ if ( ! x || typeof x !== 'object' ) return false ;
654+ if ( Array . isArray ( x ) ) return false ;
655+ for ( const _key in x ) return false ;
656+ return true ;
642657}
643658
644659type AnyConstructor = abstract new ( ...args : any [ ] ) => any ;
@@ -1083,6 +1098,28 @@ export const symbol: SymbolPattern = chainable(when(isSymbol));
10831098 */
10841099export const nullish : NullishPattern = chainable ( when ( isNullish ) ) ;
10851100
1101+ /**
1102+ * `P.object.empty()` is a pattern, matching **objects** with no keys.
1103+ *
1104+ * [Read the documentation for `P.object.empty()` on GitHub](https://github.com/gvergnaud/ts-pattern#pobjectempty)
1105+ *
1106+ * @example
1107+ * match(value)
1108+ * .with(P.object.empty(), () => 'will match on empty objects')
1109+ */
1110+ const emptyObject : EmptyObjectPattern = chainable ( when ( isEmptyObject ) ) ;
1111+
1112+ /**
1113+ * `P.object` is a wildcard pattern, matching any **object**.
1114+ *
1115+ * [Read the documentation for `P.object` on GitHub](https://github.com/gvergnaud/ts-pattern#pobject-predicates)
1116+ *
1117+ * @example
1118+ * match(value)
1119+ * .with(P.object, () => 'will match on objects')
1120+ **/
1121+ export const object : ObjectPattern = objectChainable ( when ( isObject ) ) ;
1122+
10861123/**
10871124 * `P.instanceOf(SomeClass)` is a pattern matching instances of a given class.
10881125 *
@@ -1117,40 +1154,3 @@ export function shape<input, const pattern extends Pattern<input>>(
11171154export function shape ( pattern : UnknownPattern ) {
11181155 return chainable ( when ( isMatching ( pattern ) ) ) ;
11191156}
1120-
1121- /**
1122- * `P.object.empty()` is a pattern, matching **objects** with no keys.
1123- *
1124- * [Read the documentation for `P.object.empty` on GitHub](https://github.com/gvergnaud/ts-pattern#pobjectempty)
1125- *
1126- * @example
1127- * match(value)
1128- * .with(P.object.empty(), () => 'will match on empty objects')
1129- */
1130- const emptyObject = < input > ( ) : GuardExcludeP < input , object , never > => when (
1131- ( value ) => {
1132- if ( ! isObject ( value ) ) return false ;
1133-
1134- for ( var prop in value ) return false ;
1135- return true ;
1136- } ,
1137- ) ;
1138-
1139- const objectChainable = < pattern extends Matcher < any , any , any , any , any > > (
1140- pattern : pattern
1141- ) : ObjectChainable < pattern > =>
1142- Object . assign ( chainable ( pattern ) , {
1143- empty : ( ) => chainable ( intersection ( pattern , emptyObject ( ) ) ) ,
1144- } ) as any ;
1145-
1146- /**
1147- * `P.object` is a wildcard pattern, matching any **object**.
1148- * It lets you call methods like `.empty()`, `.and`, `.or` and `.select()`
1149- * On structural patterns, like objects and arrays.
1150- * [Read the documentation for `P.object` on GitHub](https://github.com/gvergnaud/ts-pattern#pobject-predicates)
1151- *
1152- * @example
1153- * match(value)
1154- * .with(P.object.empty(), () => 'will match on empty objects')
1155- **/
1156- export const object : ObjectChainable < GuardP < unknown , object > > = objectChainable ( when ( isObject ) ) ;
0 commit comments