Skip to content

Commit 5330ea4

Browse files
committed
👍 Improve performance of isObjectOf<T>
Before to this commit, the benchmark result was is.ObjectOf 335.74 ns/iter 2,978,453.8 (307.15 ns … 694.14 ns) 337.23 ns 391.01 ns 694.14 ns is.ObjectOf (strict) 406.31 ns/iter 2,461,182.4 (386.4 ns … 453.27 ns) 413.72 ns 442.96 ns 453.27 ns is.ObjectOf (pre) 179.34 ns/iter 5,575,896.2 (167.5 ns … 196.1 ns) 185.86 ns 195.85 ns 195.88 ns is.ObjectOf (pre, strict) 205.37 ns/iter 4,869,263.2 (199.38 ns … 225.96 ns) 207.86 ns 224.33 ns 225.62 ns And after this commit is.ObjectOf 150.21 ns/iter 6,657,313.1 (144.75 ns … 161.07 ns) 152.62 ns 159.53 ns 160.82 ns is.ObjectOf (strict) 240.33 ns/iter 4,160,893.5 (233.04 ns … 276.14 ns) 241.96 ns 273.35 ns 273.55 ns is.ObjectOf (pre) 112.1 ns/iter 8,920,598.1 (108.72 ns … 124.09 ns) 112.92 ns 118.22 ns 122.38 ns is.ObjectOf (pre, strict) 137.05 ns/iter 7,296,588.7 (130.81 ns … 168.84 ns) 139.82 ns 151.59 ns 158.23 ns
1 parent 299e25b commit 5330ea4

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

is.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,35 @@ export function isObjectOf<
193193
predObj: T,
194194
options: { strict?: boolean } = {},
195195
): Predicate<ObjectOf<T>> {
196-
const preds = Object.entries(predObj);
197-
const allKeys = new Set(preds.map(([key]) => key));
198-
const requiredKeys = preds
199-
.filter(([_, pred]) => !(pred as OptionalPredicate<unknown>).optional)
200-
.map(([key]) => key);
201-
const hasKeys = options.strict
202-
? (props: string[]) => props.every((p) => allKeys.has(p))
203-
: (props: string[]) => requiredKeys.every((k) => props.includes(k));
204-
return (x: unknown): x is ObjectOf<T> =>
205-
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+
};
206225
}
207226

208227
/**

0 commit comments

Comments
 (0)