@nicolastoulemont/std 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/adt/index.d.mts +2 -0
- package/dist/adt/index.mjs +3 -0
- package/dist/adt-DraJkmij.mjs +318 -0
- package/dist/adt-DraJkmij.mjs.map +1 -0
- package/dist/apply-fn.types-CXDoeA7D.d.mts +8 -0
- package/dist/apply-fn.types-CXDoeA7D.d.mts.map +1 -0
- package/dist/brand/index.d.mts +2 -0
- package/dist/brand/index.mjs +3 -0
- package/dist/brand-CTaxGuU9.mjs +165 -0
- package/dist/brand-CTaxGuU9.mjs.map +1 -0
- package/dist/data/index.d.mts +2 -0
- package/dist/data/index.mjs +3 -0
- package/dist/data-DgzWI4R_.mjs +244 -0
- package/dist/data-DgzWI4R_.mjs.map +1 -0
- package/dist/discriminator.types-DCkkrCj4.d.mts +7 -0
- package/dist/discriminator.types-DCkkrCj4.d.mts.map +1 -0
- package/dist/either/index.d.mts +2 -0
- package/dist/either/index.mjs +3 -0
- package/dist/either-CnOBUH7a.mjs +598 -0
- package/dist/either-CnOBUH7a.mjs.map +1 -0
- package/dist/equality/index.d.mts +86 -0
- package/dist/equality/index.d.mts.map +1 -0
- package/dist/equality/index.mjs +3 -0
- package/dist/equality-YMebYwm1.mjs +201 -0
- package/dist/equality-YMebYwm1.mjs.map +1 -0
- package/dist/err/index.d.mts +2 -0
- package/dist/err/index.mjs +3 -0
- package/dist/err-BqQApH9r.mjs +169 -0
- package/dist/err-BqQApH9r.mjs.map +1 -0
- package/dist/flow/index.d.mts +2 -0
- package/dist/flow/index.mjs +3 -0
- package/dist/flow-pRdnqmMY.mjs +21 -0
- package/dist/flow-pRdnqmMY.mjs.map +1 -0
- package/dist/gen/index.d.mts +3 -0
- package/dist/gen/index.mjs +3 -0
- package/dist/gen-YfMC9sDT.mjs +42 -0
- package/dist/gen-YfMC9sDT.mjs.map +1 -0
- package/dist/index-BCrD3pEs.d.mts +222 -0
- package/dist/index-BCrD3pEs.d.mts.map +1 -0
- package/dist/index-BR7takNf.d.mts +186 -0
- package/dist/index-BR7takNf.d.mts.map +1 -0
- package/dist/index-CcPnhWje.d.mts +72 -0
- package/dist/index-CcPnhWje.d.mts.map +1 -0
- package/dist/index-CtJ8Ks9X.d.mts +105 -0
- package/dist/index-CtJ8Ks9X.d.mts.map +1 -0
- package/dist/index-CvGTIg9L.d.mts +211 -0
- package/dist/index-CvGTIg9L.d.mts.map +1 -0
- package/dist/index-DPVT0yK4.d.mts +50 -0
- package/dist/index-DPVT0yK4.d.mts.map +1 -0
- package/dist/index-DgOAEEpu.d.mts +79 -0
- package/dist/index-DgOAEEpu.d.mts.map +1 -0
- package/dist/index-Dtq3kmln.d.mts +394 -0
- package/dist/index-Dtq3kmln.d.mts.map +1 -0
- package/dist/index-bLRqTe5I.d.mts +80 -0
- package/dist/index-bLRqTe5I.d.mts.map +1 -0
- package/dist/index-tkgTLCoq.d.mts +80 -0
- package/dist/index-tkgTLCoq.d.mts.map +1 -0
- package/dist/index-wTrnFgYg.d.mts +57 -0
- package/dist/index-wTrnFgYg.d.mts.map +1 -0
- package/dist/index-yyBTq8Ys.d.mts +79 -0
- package/dist/index-yyBTq8Ys.d.mts.map +1 -0
- package/dist/index.d.mts +135 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +41 -0
- package/dist/index.mjs.map +1 -0
- package/dist/is-promise-BEl3eGZg.mjs +11 -0
- package/dist/is-promise-BEl3eGZg.mjs.map +1 -0
- package/dist/option/index.d.mts +3 -0
- package/dist/option/index.mjs +3 -0
- package/dist/option-CKHDOVea.mjs +410 -0
- package/dist/option-CKHDOVea.mjs.map +1 -0
- package/dist/option.types-D6TYG_i3.d.mts +89 -0
- package/dist/option.types-D6TYG_i3.d.mts.map +1 -0
- package/dist/pipe/index.d.mts +2 -0
- package/dist/pipe/index.mjs +3 -0
- package/dist/pipe-GYxZNkPB.mjs +10 -0
- package/dist/pipe-GYxZNkPB.mjs.map +1 -0
- package/dist/predicate/index.d.mts +2 -0
- package/dist/predicate/index.mjs +3 -0
- package/dist/predicate-B6-EdVgW.mjs +293 -0
- package/dist/predicate-B6-EdVgW.mjs.map +1 -0
- package/dist/result/index.d.mts +3 -0
- package/dist/result/index.mjs +3 -0
- package/dist/result-C5tPWR60.mjs +422 -0
- package/dist/result-C5tPWR60.mjs.map +1 -0
- package/dist/result-D7XJ96pv.mjs +1 -0
- package/dist/result.types-Ce7AEOzj.d.mts +156 -0
- package/dist/result.types-Ce7AEOzj.d.mts.map +1 -0
- package/dist/run/index.d.mts +2 -0
- package/dist/run/index.mjs +3 -0
- package/dist/run-DpXkImo9.mjs +10 -0
- package/dist/run-DpXkImo9.mjs.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
//#region src/predicate/predicate.ts
|
|
2
|
+
/**
|
|
3
|
+
* Negate a predicate.
|
|
4
|
+
* Returns true when the original predicate returns false, and vice versa.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type being tested
|
|
7
|
+
* @param predicate - The predicate to negate
|
|
8
|
+
* @returns A new predicate that returns the opposite boolean
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
13
|
+
* const isOdd = Predicate.not(isEven)
|
|
14
|
+
*
|
|
15
|
+
* isOdd(3) // true
|
|
16
|
+
* isOdd(4) // false
|
|
17
|
+
*
|
|
18
|
+
* // Works in filter
|
|
19
|
+
* [1, 2, 3, 4].filter(Predicate.not(isEven)) // [1, 3]
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
const not = (predicate) => {
|
|
23
|
+
return (value) => !predicate(value);
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Combine predicates with logical AND.
|
|
27
|
+
* Returns true only when ALL predicates return true.
|
|
28
|
+
* Short-circuits on first false (lazy evaluation).
|
|
29
|
+
*
|
|
30
|
+
* @template T - The type being tested
|
|
31
|
+
* @param predicates - The predicates to combine
|
|
32
|
+
* @returns A new predicate that returns true if all predicates pass
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const isPositive = (n: number) => n > 0
|
|
37
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
38
|
+
* const isLessThan100 = (n: number) => n < 100
|
|
39
|
+
*
|
|
40
|
+
* const isValidNumber = Predicate.and(isPositive, isEven, isLessThan100)
|
|
41
|
+
*
|
|
42
|
+
* isValidNumber(42) // true
|
|
43
|
+
* isValidNumber(-2) // false (not positive)
|
|
44
|
+
* isValidNumber(101) // false (not less than 100)
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
const and = (...predicates) => {
|
|
48
|
+
return (value) => {
|
|
49
|
+
for (const predicate of predicates) if (!predicate(value)) return false;
|
|
50
|
+
return true;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Combine predicates with logical OR.
|
|
55
|
+
* Returns true when ANY predicate returns true.
|
|
56
|
+
* Short-circuits on first true (lazy evaluation).
|
|
57
|
+
*
|
|
58
|
+
* @template T - The type being tested
|
|
59
|
+
* @param predicates - The predicates to combine
|
|
60
|
+
* @returns A new predicate that returns true if any predicate passes
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const isZero = (n: number) => n === 0
|
|
65
|
+
* const isNegative = (n: number) => n < 0
|
|
66
|
+
*
|
|
67
|
+
* const isNotPositive = Predicate.or(isZero, isNegative)
|
|
68
|
+
*
|
|
69
|
+
* isNotPositive(0) // true
|
|
70
|
+
* isNotPositive(-5) // true
|
|
71
|
+
* isNotPositive(5) // false
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
const or = (...predicates) => {
|
|
75
|
+
return (value) => {
|
|
76
|
+
for (const predicate of predicates) if (predicate(value)) return true;
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Create a predicate that tests if ALL elements in an array match.
|
|
82
|
+
* Returns true for empty arrays (vacuous truth).
|
|
83
|
+
*
|
|
84
|
+
* @template T - The element type
|
|
85
|
+
* @param predicate - The predicate to test each element
|
|
86
|
+
* @returns A predicate that takes an array and returns true if all match
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const isPositive = (n: number) => n > 0
|
|
91
|
+
* const allPositive = Predicate.every(isPositive)
|
|
92
|
+
*
|
|
93
|
+
* allPositive([1, 2, 3]) // true
|
|
94
|
+
* allPositive([1, -2, 3]) // false
|
|
95
|
+
* allPositive([]) // true (vacuous truth)
|
|
96
|
+
*
|
|
97
|
+
* // Useful for validation
|
|
98
|
+
* const areAllAdults = Predicate.every((u: User) => u.age >= 18)
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
const every = (predicate) => {
|
|
102
|
+
return (arr) => arr.every(predicate);
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Create a predicate that tests if ANY element in an array matches.
|
|
106
|
+
* Returns false for empty arrays.
|
|
107
|
+
*
|
|
108
|
+
* @template T - The element type
|
|
109
|
+
* @param predicate - The predicate to test each element
|
|
110
|
+
* @returns A predicate that takes an array and returns true if any match
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* const isNegative = (n: number) => n < 0
|
|
115
|
+
* const hasNegative = Predicate.some(isNegative)
|
|
116
|
+
*
|
|
117
|
+
* hasNegative([1, -2, 3]) // true
|
|
118
|
+
* hasNegative([1, 2, 3]) // false
|
|
119
|
+
* hasNegative([]) // false
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
const some = (predicate) => {
|
|
123
|
+
return (arr) => arr.some(predicate);
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Create a predicate that tests if NO elements in an array match.
|
|
127
|
+
* Returns true for empty arrays (vacuous truth).
|
|
128
|
+
* Equivalent to `not(some(predicate))`.
|
|
129
|
+
*
|
|
130
|
+
* @template T - The element type
|
|
131
|
+
* @param predicate - The predicate that should NOT match any element
|
|
132
|
+
* @returns A predicate that takes an array and returns true if none match
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* const isNegative = (n: number) => n < 0
|
|
137
|
+
* const noNegatives = Predicate.none(isNegative)
|
|
138
|
+
*
|
|
139
|
+
* noNegatives([1, 2, 3]) // true
|
|
140
|
+
* noNegatives([1, -2, 3]) // false
|
|
141
|
+
* noNegatives([]) // true (vacuous truth)
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
const none = (predicate) => {
|
|
145
|
+
return (arr) => !arr.some(predicate);
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Combine refinements with logical AND, preserving type narrowing.
|
|
149
|
+
* Use this instead of `and` when you need to preserve type guard behavior.
|
|
150
|
+
*
|
|
151
|
+
* @template T - The base type
|
|
152
|
+
* @template U - The narrowed type (must extend T)
|
|
153
|
+
* @param refinements - The refinements to combine
|
|
154
|
+
* @returns A refinement that narrows to U if all refinements pass
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* type User = { name: string; age: number; verified?: boolean }
|
|
159
|
+
* type Adult = User & { age: number } // age >= 18
|
|
160
|
+
* type VerifiedAdult = Adult & { verified: true }
|
|
161
|
+
*
|
|
162
|
+
* const isAdult = (u: User): u is Adult => u.age >= 18
|
|
163
|
+
* const isVerified = (u: User): u is User & { verified: true } => u.verified === true
|
|
164
|
+
*
|
|
165
|
+
* // Combined refinement preserves type narrowing
|
|
166
|
+
* const isVerifiedAdult = Predicate.andRefinement<User, VerifiedAdult>(isAdult, isVerified)
|
|
167
|
+
*
|
|
168
|
+
* if (isVerifiedAdult(user)) {
|
|
169
|
+
* user.verified // TypeScript knows this is true
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
const andRefinement = (...refinements) => {
|
|
174
|
+
return (value) => {
|
|
175
|
+
for (const refinement of refinements) if (!refinement(value)) return false;
|
|
176
|
+
return true;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Combine refinements with logical OR, preserving type narrowing.
|
|
181
|
+
* Use this instead of `or` when you need to preserve type guard behavior.
|
|
182
|
+
*
|
|
183
|
+
* @template T - The base type
|
|
184
|
+
* @template U - The narrowed type (must extend T)
|
|
185
|
+
* @param refinements - The refinements to combine
|
|
186
|
+
* @returns A refinement that narrows to U if any refinement passes
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* const isString = (v: unknown): v is string => typeof v === "string"
|
|
191
|
+
* const isNumber = (v: unknown): v is number => typeof v === "number"
|
|
192
|
+
*
|
|
193
|
+
* const isStringOrNumber = Predicate.orRefinement<unknown, string | number>(isString, isNumber)
|
|
194
|
+
*
|
|
195
|
+
* if (isStringOrNumber(value)) {
|
|
196
|
+
* // value is string | number
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
const orRefinement = (...refinements) => {
|
|
201
|
+
return (value) => {
|
|
202
|
+
for (const refinement of refinements) if (refinement(value)) return true;
|
|
203
|
+
return false;
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Create a predicate from a constant boolean value.
|
|
208
|
+
* Useful for testing or as a placeholder.
|
|
209
|
+
*
|
|
210
|
+
* @template T - The type (can be anything)
|
|
211
|
+
* @param value - The constant boolean to return
|
|
212
|
+
* @returns A predicate that always returns the given value
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* const alwaysTrue = Predicate.constant(true)
|
|
217
|
+
* const alwaysFalse = Predicate.constant(false)
|
|
218
|
+
*
|
|
219
|
+
* alwaysTrue("anything") // true
|
|
220
|
+
* alwaysFalse(42) // false
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
const constant = (value) => {
|
|
224
|
+
return () => value;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Create a predicate that checks strict equality.
|
|
228
|
+
*
|
|
229
|
+
* @template T - The type being compared
|
|
230
|
+
* @param expected - The value to compare against
|
|
231
|
+
* @returns A predicate that returns true if value === expected
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* const isZero = Predicate.equals(0)
|
|
236
|
+
* const isHello = Predicate.equals("hello")
|
|
237
|
+
*
|
|
238
|
+
* isZero(0) // true
|
|
239
|
+
* isZero(1) // false
|
|
240
|
+
*
|
|
241
|
+
* // Works with references too
|
|
242
|
+
* const obj = { a: 1 }
|
|
243
|
+
* const isObj = Predicate.equals(obj)
|
|
244
|
+
* isObj(obj) // true
|
|
245
|
+
* isObj({ a: 1 }) // false (different reference)
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
const equals = (expected) => {
|
|
249
|
+
return (value) => value === expected;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Predicate namespace containing composable boolean functions.
|
|
253
|
+
*
|
|
254
|
+
* Predicates are functions that test values and return booleans.
|
|
255
|
+
* This namespace provides combinators to build complex predicates
|
|
256
|
+
* from simple ones, with support for type guards (refinements).
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* import { Predicate, pipe } from "@repo/std"
|
|
261
|
+
*
|
|
262
|
+
* // Basic predicates
|
|
263
|
+
* const isPositive = (n: number) => n > 0
|
|
264
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
265
|
+
*
|
|
266
|
+
* // Combine with and/or
|
|
267
|
+
* const isPositiveEven = Predicate.and(isPositive, isEven)
|
|
268
|
+
* const isZeroOrNegative = Predicate.or(Predicate.equals(0), Predicate.not(isPositive))
|
|
269
|
+
*
|
|
270
|
+
* // Array predicates
|
|
271
|
+
* const allPositive = Predicate.every(isPositive)
|
|
272
|
+
* const hasNegative = Predicate.some(Predicate.not(isPositive))
|
|
273
|
+
*
|
|
274
|
+
* // Use with filter
|
|
275
|
+
* [1, 2, 3, 4, 5].filter(isPositiveEven) // [2, 4]
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
const Predicate = {
|
|
279
|
+
not,
|
|
280
|
+
and,
|
|
281
|
+
or,
|
|
282
|
+
every,
|
|
283
|
+
some,
|
|
284
|
+
none,
|
|
285
|
+
andRefinement,
|
|
286
|
+
orRefinement,
|
|
287
|
+
constant,
|
|
288
|
+
equals
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
//#endregion
|
|
292
|
+
export { Predicate as t };
|
|
293
|
+
//# sourceMappingURL=predicate-B6-EdVgW.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate-B6-EdVgW.mjs","names":[],"sources":["../src/predicate/predicate.ts"],"sourcesContent":["import type { Predicate as PredicateType, Refinement } from \"./predicate.types\"\n\n/**\n * Negate a predicate.\n * Returns true when the original predicate returns false, and vice versa.\n *\n * @template T - The type being tested\n * @param predicate - The predicate to negate\n * @returns A new predicate that returns the opposite boolean\n *\n * @example\n * ```ts\n * const isEven = (n: number) => n % 2 === 0\n * const isOdd = Predicate.not(isEven)\n *\n * isOdd(3) // true\n * isOdd(4) // false\n *\n * // Works in filter\n * [1, 2, 3, 4].filter(Predicate.not(isEven)) // [1, 3]\n * ```\n */\nexport const not = <T>(predicate: PredicateType<T>): PredicateType<T> => {\n return (value: T): boolean => !predicate(value)\n}\n\n/**\n * Combine predicates with logical AND.\n * Returns true only when ALL predicates return true.\n * Short-circuits on first false (lazy evaluation).\n *\n * @template T - The type being tested\n * @param predicates - The predicates to combine\n * @returns A new predicate that returns true if all predicates pass\n *\n * @example\n * ```ts\n * const isPositive = (n: number) => n > 0\n * const isEven = (n: number) => n % 2 === 0\n * const isLessThan100 = (n: number) => n < 100\n *\n * const isValidNumber = Predicate.and(isPositive, isEven, isLessThan100)\n *\n * isValidNumber(42) // true\n * isValidNumber(-2) // false (not positive)\n * isValidNumber(101) // false (not less than 100)\n * ```\n */\nexport const and = <T>(...predicates: readonly PredicateType<T>[]): PredicateType<T> => {\n return (value: T): boolean => {\n for (const predicate of predicates) {\n if (!predicate(value)) return false\n }\n return true\n }\n}\n\n/**\n * Combine predicates with logical OR.\n * Returns true when ANY predicate returns true.\n * Short-circuits on first true (lazy evaluation).\n *\n * @template T - The type being tested\n * @param predicates - The predicates to combine\n * @returns A new predicate that returns true if any predicate passes\n *\n * @example\n * ```ts\n * const isZero = (n: number) => n === 0\n * const isNegative = (n: number) => n < 0\n *\n * const isNotPositive = Predicate.or(isZero, isNegative)\n *\n * isNotPositive(0) // true\n * isNotPositive(-5) // true\n * isNotPositive(5) // false\n * ```\n */\nexport const or = <T>(...predicates: readonly PredicateType<T>[]): PredicateType<T> => {\n return (value: T): boolean => {\n for (const predicate of predicates) {\n if (predicate(value)) return true\n }\n return false\n }\n}\n\n/**\n * Create a predicate that tests if ALL elements in an array match.\n * Returns true for empty arrays (vacuous truth).\n *\n * @template T - The element type\n * @param predicate - The predicate to test each element\n * @returns A predicate that takes an array and returns true if all match\n *\n * @example\n * ```ts\n * const isPositive = (n: number) => n > 0\n * const allPositive = Predicate.every(isPositive)\n *\n * allPositive([1, 2, 3]) // true\n * allPositive([1, -2, 3]) // false\n * allPositive([]) // true (vacuous truth)\n *\n * // Useful for validation\n * const areAllAdults = Predicate.every((u: User) => u.age >= 18)\n * ```\n */\nexport const every = <T>(predicate: PredicateType<T>): PredicateType<readonly T[]> => {\n return (arr: readonly T[]): boolean => arr.every(predicate)\n}\n\n/**\n * Create a predicate that tests if ANY element in an array matches.\n * Returns false for empty arrays.\n *\n * @template T - The element type\n * @param predicate - The predicate to test each element\n * @returns A predicate that takes an array and returns true if any match\n *\n * @example\n * ```ts\n * const isNegative = (n: number) => n < 0\n * const hasNegative = Predicate.some(isNegative)\n *\n * hasNegative([1, -2, 3]) // true\n * hasNegative([1, 2, 3]) // false\n * hasNegative([]) // false\n * ```\n */\nexport const some = <T>(predicate: PredicateType<T>): PredicateType<readonly T[]> => {\n return (arr: readonly T[]): boolean => arr.some(predicate)\n}\n\n/**\n * Create a predicate that tests if NO elements in an array match.\n * Returns true for empty arrays (vacuous truth).\n * Equivalent to `not(some(predicate))`.\n *\n * @template T - The element type\n * @param predicate - The predicate that should NOT match any element\n * @returns A predicate that takes an array and returns true if none match\n *\n * @example\n * ```ts\n * const isNegative = (n: number) => n < 0\n * const noNegatives = Predicate.none(isNegative)\n *\n * noNegatives([1, 2, 3]) // true\n * noNegatives([1, -2, 3]) // false\n * noNegatives([]) // true (vacuous truth)\n * ```\n */\nexport const none = <T>(predicate: PredicateType<T>): PredicateType<readonly T[]> => {\n return (arr: readonly T[]): boolean => !arr.some(predicate)\n}\n\n/**\n * Combine refinements with logical AND, preserving type narrowing.\n * Use this instead of `and` when you need to preserve type guard behavior.\n *\n * @template T - The base type\n * @template U - The narrowed type (must extend T)\n * @param refinements - The refinements to combine\n * @returns A refinement that narrows to U if all refinements pass\n *\n * @example\n * ```ts\n * type User = { name: string; age: number; verified?: boolean }\n * type Adult = User & { age: number } // age >= 18\n * type VerifiedAdult = Adult & { verified: true }\n *\n * const isAdult = (u: User): u is Adult => u.age >= 18\n * const isVerified = (u: User): u is User & { verified: true } => u.verified === true\n *\n * // Combined refinement preserves type narrowing\n * const isVerifiedAdult = Predicate.andRefinement<User, VerifiedAdult>(isAdult, isVerified)\n *\n * if (isVerifiedAdult(user)) {\n * user.verified // TypeScript knows this is true\n * }\n * ```\n */\nexport const andRefinement = <T, U extends T>(...refinements: readonly Refinement<T, U>[]): Refinement<T, U> => {\n return (value: T): value is U => {\n for (const refinement of refinements) {\n if (!refinement(value)) return false\n }\n return true\n }\n}\n\n/**\n * Combine refinements with logical OR, preserving type narrowing.\n * Use this instead of `or` when you need to preserve type guard behavior.\n *\n * @template T - The base type\n * @template U - The narrowed type (must extend T)\n * @param refinements - The refinements to combine\n * @returns A refinement that narrows to U if any refinement passes\n *\n * @example\n * ```ts\n * const isString = (v: unknown): v is string => typeof v === \"string\"\n * const isNumber = (v: unknown): v is number => typeof v === \"number\"\n *\n * const isStringOrNumber = Predicate.orRefinement<unknown, string | number>(isString, isNumber)\n *\n * if (isStringOrNumber(value)) {\n * // value is string | number\n * }\n * ```\n */\nexport const orRefinement = <T, U extends T>(...refinements: readonly Refinement<T, U>[]): Refinement<T, U> => {\n return (value: T): value is U => {\n for (const refinement of refinements) {\n if (refinement(value)) return true\n }\n return false\n }\n}\n\n/**\n * Create a predicate from a constant boolean value.\n * Useful for testing or as a placeholder.\n *\n * @template T - The type (can be anything)\n * @param value - The constant boolean to return\n * @returns A predicate that always returns the given value\n *\n * @example\n * ```ts\n * const alwaysTrue = Predicate.constant(true)\n * const alwaysFalse = Predicate.constant(false)\n *\n * alwaysTrue(\"anything\") // true\n * alwaysFalse(42) // false\n * ```\n */\nexport const constant = <T>(value: boolean): PredicateType<T> => {\n return (): boolean => value\n}\n\n/**\n * Create a predicate that checks strict equality.\n *\n * @template T - The type being compared\n * @param expected - The value to compare against\n * @returns A predicate that returns true if value === expected\n *\n * @example\n * ```ts\n * const isZero = Predicate.equals(0)\n * const isHello = Predicate.equals(\"hello\")\n *\n * isZero(0) // true\n * isZero(1) // false\n *\n * // Works with references too\n * const obj = { a: 1 }\n * const isObj = Predicate.equals(obj)\n * isObj(obj) // true\n * isObj({ a: 1 }) // false (different reference)\n * ```\n */\nexport const equals = <T>(expected: T): PredicateType<T> => {\n return (value: T): boolean => value === expected\n}\n\n/**\n * Predicate namespace containing composable boolean functions.\n *\n * Predicates are functions that test values and return booleans.\n * This namespace provides combinators to build complex predicates\n * from simple ones, with support for type guards (refinements).\n *\n * @example\n * ```ts\n * import { Predicate, pipe } from \"@repo/std\"\n *\n * // Basic predicates\n * const isPositive = (n: number) => n > 0\n * const isEven = (n: number) => n % 2 === 0\n *\n * // Combine with and/or\n * const isPositiveEven = Predicate.and(isPositive, isEven)\n * const isZeroOrNegative = Predicate.or(Predicate.equals(0), Predicate.not(isPositive))\n *\n * // Array predicates\n * const allPositive = Predicate.every(isPositive)\n * const hasNegative = Predicate.some(Predicate.not(isPositive))\n *\n * // Use with filter\n * [1, 2, 3, 4, 5].filter(isPositiveEven) // [2, 4]\n * ```\n */\nexport const Predicate = {\n not,\n and,\n or,\n every,\n some,\n none,\n andRefinement,\n orRefinement,\n constant,\n equals,\n} as const\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,OAAU,cAAkD;AACvE,SAAQ,UAAsB,CAAC,UAAU,MAAM;;;;;;;;;;;;;;;;;;;;;;;;AAyBjD,MAAa,OAAU,GAAG,eAA8D;AACtF,SAAQ,UAAsB;AAC5B,OAAK,MAAM,aAAa,WACtB,KAAI,CAAC,UAAU,MAAM,CAAE,QAAO;AAEhC,SAAO;;;;;;;;;;;;;;;;;;;;;;;;AAyBX,MAAa,MAAS,GAAG,eAA8D;AACrF,SAAQ,UAAsB;AAC5B,OAAK,MAAM,aAAa,WACtB,KAAI,UAAU,MAAM,CAAE,QAAO;AAE/B,SAAO;;;;;;;;;;;;;;;;;;;;;;;;AAyBX,MAAa,SAAY,cAA6D;AACpF,SAAQ,QAA+B,IAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;AAqB7D,MAAa,QAAW,cAA6D;AACnF,SAAQ,QAA+B,IAAI,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;;AAsB5D,MAAa,QAAW,cAA6D;AACnF,SAAQ,QAA+B,CAAC,IAAI,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B7D,MAAa,iBAAiC,GAAG,gBAA+D;AAC9G,SAAQ,UAAyB;AAC/B,OAAK,MAAM,cAAc,YACvB,KAAI,CAAC,WAAW,MAAM,CAAE,QAAO;AAEjC,SAAO;;;;;;;;;;;;;;;;;;;;;;;;AAyBX,MAAa,gBAAgC,GAAG,gBAA+D;AAC7G,SAAQ,UAAyB;AAC/B,OAAK,MAAM,cAAc,YACvB,KAAI,WAAW,MAAM,CAAE,QAAO;AAEhC,SAAO;;;;;;;;;;;;;;;;;;;;AAqBX,MAAa,YAAe,UAAqC;AAC/D,cAAsB;;;;;;;;;;;;;;;;;;;;;;;;AAyBxB,MAAa,UAAa,aAAkC;AAC1D,SAAQ,UAAsB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B1C,MAAa,YAAY;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
|