-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpredicates.js
62 lines (55 loc) · 1.69 KB
/
predicates.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import {curry, curriedFunction, partialArgs, originalFunction} from "./curry.js"
export const which = curry(function(predicate, x) {
return predicate(x)
}, "which")
export const equals = curry(function(a, b) {
if (isCustomMatcher(a)) {
return a(b)
}
if (Array.isArray(a) && Array.isArray(b)) {
return a.length === b.length
&& a.every((_, i) => equals(a[i], b[i]))
}
if (a instanceof Function && b instanceof Function) {
if (originalFunction(a) && originalFunction(a) === originalFunction(b)) {
return equals(partialArgs(a), partialArgs(b))
}
return a === b
}
if (a instanceof Date && b instanceof Date) {
return a.toISOString() === b.toISOString()
}
if (a instanceof Set && b instanceof Set) {
return a.size === b.size
&& [...a.values()].every(v => b.has(v))
}
if (a instanceof Error && b instanceof Error) {
return a.message === b.message
&& a.__proto__.constructor === b.__proto__.constructor
}
if (isObject(a) && isObject(b)) {
const aKeys = Object.keys(a)
const bKeys = Object.keys(b)
return aKeys.length === bKeys.length
&& aKeys.every(k => equals(a[k], b[k]))
&& a.__proto__?.constructor === b.__proto__?.constructor
}
return a === b
}, "equals")
export const is = curry(function(a, b) {
return a === b
}, "is")
export const not = curry(function(predicate, subject, ...args) {
return !predicate(subject, ...args)
}, "not")
export const isBlank = curry(function(s) {
return /^\s*$/.test(s)
}, "isBlank")
function isObject(x) {
return !!x && typeof x === "object"
}
function isCustomMatcher(f) {
return f instanceof Function
&& curriedFunction(f) === which
&& partialArgs(f).length === 1
}