@@ -36,6 +36,8 @@ import {
3636 Variadic ,
3737 NonNullablePattern ,
3838 ObjectChainable ,
39+ ObjectPattern ,
40+ EmptyObjectPattern ,
3941} from './types/Pattern' ;
4042
4143export type { Pattern , Fn as unstable_Fn } ;
@@ -157,6 +159,14 @@ function arrayChainable<pattern extends Matcher<any, any, any, any, any>>(
157159 } ) as any ;
158160}
159161
162+ function objectChainable < pattern extends Matcher < any , any , any , any , any > > (
163+ pattern : pattern
164+ ) : ObjectChainable < pattern > {
165+ return Object . assign ( chainable ( pattern ) , {
166+ empty : ( ) => emptyObject ,
167+ } ) as any ;
168+ }
169+
160170/**
161171 * `P.optional(subpattern)` takes a sub pattern and returns a pattern which matches if the
162172 * key is undefined or if it is defined and the sub pattern matches its value.
@@ -640,8 +650,15 @@ function isNonNullable(x: unknown): x is {} {
640650 return x !== null && x !== undefined ;
641651}
642652
643- function isObject < T > ( x : T | object ) : x is object {
644- return typeof x === 'object' && ! Array . isArray ( x ) && x !== null ;
653+ function isObject ( x : unknown ) : x is object {
654+ return ! ! x && ( typeof x === 'object' || typeof x === 'function' ) ;
655+ }
656+
657+ function isEmptyObject ( x : unknown ) {
658+ if ( ! x || typeof x !== 'object' ) return false ;
659+ if ( Array . isArray ( x ) ) return false ;
660+ for ( const _key in x ) return false ;
661+ return true ;
645662}
646663
647664type AnyConstructor = abstract new ( ...args : any [ ] ) => any ;
@@ -1096,6 +1113,28 @@ export const nullish: NullishPattern = chainable(when(isNullish));
10961113 */
10971114export const nonNullable : NonNullablePattern = chainable ( when ( isNonNullable ) ) ;
10981115
1116+ /**
1117+ * `P.object.empty()` is a pattern, matching **objects** with no keys.
1118+ *
1119+ * [Read the documentation for `P.object.empty()` on GitHub](https://github.com/gvergnaud/ts-pattern#pobjectempty)
1120+ *
1121+ * @example
1122+ * match(value)
1123+ * .with(P.object.empty(), () => 'will match on empty objects')
1124+ */
1125+ const emptyObject : EmptyObjectPattern = chainable ( when ( isEmptyObject ) ) ;
1126+
1127+ /**
1128+ * `P.object` is a wildcard pattern, matching any **object**.
1129+ *
1130+ * [Read the documentation for `P.object` on GitHub](https://github.com/gvergnaud/ts-pattern#pobject-predicates)
1131+ *
1132+ * @example
1133+ * match(value)
1134+ * .with(P.object, () => 'will match on objects')
1135+ **/
1136+ export const object : ObjectPattern = objectChainable ( when ( isObject ) ) ;
1137+
10991138/**
11001139 * `P.instanceOf(SomeClass)` is a pattern matching instances of a given class.
11011140 *
@@ -1130,39 +1169,3 @@ export function shape<input, const pattern extends Pattern<input>>(
11301169export function shape ( pattern : UnknownPattern ) {
11311170 return chainable ( when ( isMatching ( pattern ) ) ) ;
11321171}
1133-
1134- /**
1135- * `P.object.empty()` is a pattern, matching **objects** with no keys.
1136- *
1137- * [Read the documentation for `P.object.empty` on GitHub](https://github.com/gvergnaud/ts-pattern#pobjectempty)
1138- *
1139- * @example
1140- * match(value)
1141- * .with(P.object.empty(), () => 'will match on empty objects')
1142- */
1143- const emptyObject = < input > ( ) : GuardExcludeP < input , object , never > =>
1144- when ( ( value ) => {
1145- if ( ! isObject ( value ) ) return false ;
1146-
1147- for ( var prop in value ) return false ;
1148- return true ;
1149- } ) ;
1150-
1151- const objectChainable = < pattern extends Matcher < any , any , any , any , any > > (
1152- pattern : pattern
1153- ) : ObjectChainable < pattern > =>
1154- Object . assign ( chainable ( pattern ) , {
1155- empty : ( ) => chainable ( intersection ( pattern , emptyObject ( ) ) ) ,
1156- } ) as any ;
1157-
1158- /**
1159- * `P.object` is a wildcard pattern, matching any **object**.
1160- * It lets you call methods like `.empty()`, `.and`, `.or` and `.select()`
1161- * On structural patterns, like objects and arrays.
1162- * [Read the documentation for `P.object` on GitHub](https://github.com/gvergnaud/ts-pattern#pobject-predicates)
1163- *
1164- * @example
1165- * match(value)
1166- * .with(P.object.empty(), () => 'will match on empty objects')
1167- **/
1168- export const object : ObjectChainable < GuardP < unknown , object > > = objectChainable ( when ( isObject ) ) ;
0 commit comments