@@ -138,8 +138,13 @@ export function isRecord(
138138export function isRecordOf < T > (
139139 pred : Predicate < T > ,
140140) : Predicate < RecordOf < T > > {
141- return ( x : unknown ) : x is RecordOf < T > =>
142- isRecord ( x ) && Object . values ( x ) . every ( pred ) ;
141+ return ( x : unknown ) : x is RecordOf < T > => {
142+ if ( ! isRecord ( x ) ) return false ;
143+ for ( const k in x ) {
144+ if ( ! pred ( x [ k ] ) ) return false ;
145+ }
146+ return true ;
147+ } ;
143148}
144149
145150type FlatType < T > = T extends RecordOf < unknown >
@@ -188,16 +193,35 @@ export function isObjectOf<
188193 predObj : T ,
189194 options : { strict ?: boolean } = { } ,
190195) : Predicate < ObjectOf < T > > {
191- const preds = Object . entries ( predObj ) ;
192- const allKeys = new Set ( preds . map ( ( [ key ] ) => key ) ) ;
193- const requiredKeys = preds
194- . filter ( ( [ _ , pred ] ) => ! ( pred as OptionalPredicate < unknown > ) . optional )
195- . map ( ( [ key ] ) => key ) ;
196- const hasKeys = options . strict
197- ? ( props : string [ ] ) => props . every ( ( p ) => allKeys . has ( p ) )
198- : ( props : string [ ] ) => requiredKeys . every ( ( k ) => props . includes ( k ) ) ;
199- return ( x : unknown ) : x is ObjectOf < T > =>
200- isRecord ( x ) && hasKeys ( Object . keys ( x ) ) && preds . every ( ( [ k , p ] ) => p ( x [ k ] ) ) ;
196+ return options . strict ? isObjectOfStrict ( predObj ) : isObjectOfLoose ( predObj ) ;
197+ }
198+
199+ function isObjectOfLoose <
200+ T extends RecordOf < Predicate < unknown > > ,
201+ > (
202+ predObj : T ,
203+ ) : Predicate < ObjectOf < T > > {
204+ return ( x : unknown ) : x is ObjectOf < T > => {
205+ if ( ! isRecord ( x ) ) return false ;
206+ for ( const k in predObj ) {
207+ if ( ! predObj [ k ] ( x [ k ] ) ) return false ;
208+ }
209+ return true ;
210+ } ;
211+ }
212+
213+ function isObjectOfStrict <
214+ T extends RecordOf < Predicate < unknown > > ,
215+ > (
216+ predObj : T ,
217+ ) : Predicate < ObjectOf < T > > {
218+ const keys = new Set ( Object . keys ( predObj ) ) ;
219+ const pred = isObjectOfLoose ( predObj ) ;
220+ return ( x : unknown ) : x is ObjectOf < T > => {
221+ if ( ! pred ( x ) ) return false ;
222+ const ks = Object . keys ( x ) ;
223+ return ks . length <= keys . size && ks . every ( ( k ) => keys . has ( k ) ) ;
224+ } ;
201225}
202226
203227/**
@@ -366,9 +390,12 @@ export type OptionalPredicate<T> = Predicate<T | undefined> & {
366390export function isOptionalOf < T > (
367391 pred : Predicate < T > ,
368392) : OptionalPredicate < T > {
369- return Object . assign ( isOneOf ( [ isUndefined , pred ] ) , {
370- optional : true as const ,
371- } ) ;
393+ return Object . assign (
394+ ( x : unknown ) : x is Predicate < T | undefined > => isUndefined ( x ) || pred ( x ) ,
395+ {
396+ optional : true as const ,
397+ } ,
398+ ) as OptionalPredicate < T > ;
372399}
373400
374401export default {
0 commit comments