1/**
2 * Defines runtime checks for values.
3 *
4 * A `Predicate<A>` returns `true` or `false` for an `A`. A
5 * `Refinement<A, B>` is a predicate that also narrows the TypeScript type when
6 * it succeeds. This module includes guards for common JavaScript values,
7 * property and tag checks, tuple and struct checks, boolean combinators, and
8 * helpers for composing predicates and refinements.
9 *
10 * @since 2.0.0
11 */
12import { dual } from "./Function.ts"
13import type { TypeLambda } from "./HKT.ts"
14import type { TupleOf, TupleOfAtLeast } from "./Types.ts"
15
16/**
17 * A function that decides whether a value of type `A` satisfies a condition.
18 *
19 * **When to use**
20 *
21 * Use when you want a reusable boolean check for `A`, especially when you plan
22 * to combine checks with {@link and}/{@link or} or pass a predicate to arrays
23 * and iterables.
24 *
25 * **Details**
26 *
27 * A predicate returns `true` or `false` and never throws by itself. It does not
28 * narrow types unless you use `Refinement`.
29 *
30 * **Example** (Defining a predicate)
31 *
32 * ```ts import.meta.vitest
33 * import { Predicate } from "effect"
34 *
35 * const isPositive: Predicate.Predicate<number> = (n) => n > 0
36 *
37 * isPositive(1) // => true
38 * ```
39 *
40 * @see {@link Refinement}
41 * @see {@link mapInput}
42 * @see {@link and}
43 * @category models
44 * @since 2.0.0
45 */
46export interface Predicate<in A> {
47 (a: A): boolean
48}
49
50/**
51 * Type-level lambda for higher-kinded usage of {@link Predicate}.
52 *
53 * **When to use**
54 *
55 * Use when you are defining APIs that abstract over predicates with HKTs and
56 * need a `TypeLambda` instance for predicate-based type classes.
57 *
58 * **Details**
59 *
60 * This is type-only, creates no runtime value, and does not affect emitted
61 * JavaScript.
62 *
63 * **Example** (Type-level usage)
64 *
65 * ```ts import.meta.vitest
66 * import { Predicate } from "effect"
67 *
68 * type P = Predicate.Predicate<number>
69 * type TL = Predicate.PredicateTypeLambda
70 *
71 * const witness: P = (value) => value > 0
72 * witness(1) // => true
73 * ```
74 *
75 * @see {@link Predicate}
76 * @category utility types
77 * @since 2.0.0
78 */
79export interface PredicateTypeLambda extends TypeLambda {
80 readonly type: Predicate<this["Target"]>
81}
82
83/**
84 * A predicate that also narrows the input type when it returns `true`.
85 *
86 * **When to use**
87 *
88 * Use when you want a runtime check that refines `A` to `B` for TypeScript,
89 * especially when composing type guards with {@link compose} or safely
90 * checking `unknown` values.
91 *
92 * **Details**
93 *
94 * A refinement returns a type predicate (`a is B`). Use it with `if` or
95 * `filter` to narrow types.
96 *
97 * **Example** (Narrowing unknown values)
98 *
99 * ```ts import.meta.vitest
100 * import { Predicate } from "effect"
101 *
102 * const isString: Predicate.Refinement<unknown, string> = (u): u is string => typeof u === "string"
103 *
104 * const data: unknown = "hello"
105 * if (isString(data)) {
106 * data.toUpperCase() // => "HELLO"
107 * }
108 * ```
109 *
110 * @see {@link Predicate}
111 * @see {@link compose}
112 * @see {@link isString}
113 * @category models
114 * @since 2.0.0
115 */
116export interface Refinement<in A, out B extends A> {
117 (a: A): a is B
118}
119
120/**
121 * Type-level utilities for working with {@link Predicate} types.
122 *
123 * **When to use**
124 *
125 * Use when you need to extract input types from predicate signatures while
126 * writing generic helpers over predicate types.
127 *
128 * **Details**
129 *
130 * These utilities are type-only, create no runtime values, and the namespace is
131 * erased at runtime.
132 *
133 * **Example** (Extracting predicate input)
134 *
135 * ```ts import.meta.vitest
136 * import { Predicate } from "effect"
137 *
138 * type IsString = Predicate.Predicate<string>
139 * type Input = Predicate.Predicate.In<IsString>
140 *
141 * const input: Input = "value"
142 * ```
143 *
144 * @see {@link Predicate}
145 * @see {@link Refinement}
146 * @since 3.6.0
147 */
148export declare namespace Predicate {
149 /**
150 * Extracts the input type `A` from a `Predicate<A>`.
151 *
152 * **When to use**
153 *
154 * Use when you want to infer the input type from a predicate type while
155 * defining generic utilities over predicates.
156 *
157 * **Details**
158 *
159 * This is type-only and creates no runtime value. It resolves to `never` if
160 * the type does not match `Predicate`.
161 *
162 * **Example** (Inferring the input type)
163 *
164 * ```ts import.meta.vitest
165 * import { Predicate } from "effect"
166 *
167 * type P = Predicate.Predicate<number>
168 * type Input = Predicate.Predicate.In<P>
169 *
170 * const input: Input = 1
171 * ```
172 *
173 * @see {@link Predicate.Any}
174 * @see {@link Refinement.In}
175 * @category utility types
176 * @since 3.6.0
177 */
178 export type In<T extends Any> = [T] extends [Predicate<infer _A>] ? _A : never
179
180 /**
181 * A utility type representing any predicate type.
182 *
183 * **When to use**
184 *
185 * Use when you need a constraint for "any predicate" in generic code.
186 *
187 * **Details**
188 *
189 * This is type-only and creates no runtime value.
190 *
191 * **Example** (Using generic constraints)
192 *
193 * ```ts import.meta.vitest
194 * import { Predicate } from "effect"
195 *
196 * type AnyPredicate = Predicate.Predicate.Any
197 *
198 * const witness: AnyPredicate = () => true
199 * witness("value") // => true
200 * ```
201 *
202 * @see {@link Predicate.In}
203 * @category utility types
204 * @since 3.6.0
205 */
206 export type Any = Predicate<any>
207}
208
209/**
210 * Type-level utilities for working with {@link Refinement} types.
211 *
212 * **When to use**
213 *
214 * Use when you need to extract input and output types from refinement
215 * signatures while writing generic helpers over refinements.
216 *
217 * **Details**
218 *
219 * These utilities are type-only, create no runtime values, and the namespace is
220 * erased at runtime.
221 *
222 * **Example** (Extracting refinement types)
223 *
224 * ```ts import.meta.vitest
225 * import { Predicate } from "effect"
226 *
227 * type IsString = Predicate.Refinement<unknown, string>
228 * type Input = Predicate.Refinement.In<IsString>
229 * type Output = Predicate.Refinement.Out<IsString>
230 *
231 * const output: Output = "value"
232 * ```
233 *
234 * @see {@link Refinement}
235 * @see {@link Predicate}
236 * @since 3.6.0
237 */
238export declare namespace Refinement {
239 /**
240 * Extracts the input type `A` from a `Refinement<A, B>`.
241 *
242 * **When to use**
243 *
244 * Use when you want to infer the input type from a refinement type.
245 *
246 * **Details**
247 *
248 * This is type-only and creates no runtime value. It resolves to `never` if
249 * the type does not match `Refinement`.
250 *
251 * **Example** (Inferring the input type)
252 *
253 * ```ts import.meta.vitest
254 * import { Predicate } from "effect"
255 *
256 * type R = Predicate.Refinement<unknown, string>
257 * type Input = Predicate.Refinement.In<R>
258 *
259 * const input: Input = "value"
260 * ```
261 *
262 * @see {@link Refinement.Out}
263 * @see {@link Predicate.In}
264 * @category utility types
265 * @since 3.6.0
266 */
267
268 export type In<T extends Any> = [T] extends [Refinement<infer _A, infer _>] ? _A : never
269
270 /**
271 * Extracts the output type `B` from a `Refinement<A, B>`.
272 *
273 * **When to use**
274 *
275 * Use when you want to infer the narrowed type from a refinement type.
276 *
277 * **Details**
278 *
279 * This is type-only and creates no runtime value. It resolves to `never` if
280 * the type does not match `Refinement`.
281 *
282 * **Example** (Inferring the output type)
283 *
284 * ```ts import.meta.vitest
285 * import { Predicate } from "effect"
286 *
287 * type R = Predicate.Refinement<unknown, string>
288 * type Output = Predicate.Refinement.Out<R>
289 *
290 * const output: Output = "value"
291 * ```
292 *
293 * @see {@link Refinement.In}
294 * @category utility types
295 * @since 3.6.0
296 */
297 export type Out<T extends Any> = [T] extends [Refinement<infer _, infer _B>] ? _B : never
298
299 /**
300 * A utility type representing any refinement type.
301 *
302 * **When to use**
303 *
304 * Use when you need a constraint for "any refinement" in generic code.
305 *
306 * **Details**
307 *
308 * This is type-only and creates no runtime value.
309 *
310 * **Example** (Using generic constraints)
311 *
312 * ```ts import.meta.vitest
313 * import { Predicate } from "effect"
314 *
315 * type AnyRefinement = Predicate.Refinement.Any
316 *
317 * const witness: AnyRefinement = (_): _ is string => true
318 * witness("value") // => true
319 * ```
320 *
321 * @see {@link Refinement.In}
322 * @see {@link Refinement.Out}
323 * @category utility types
324 * @since 3.6.0
325 */
326 export type Any = Refinement<any, any>
327}
328
329/**
330 * Transforms the input of a predicate using a mapping function.
331 *
332 * **When to use**
333 *
334 * Use when you have a predicate on `A` and want to check `B` values by mapping
335 * each `B` to an `A`, such as checking lengths or projections.
336 *
337 * **Details**
338 *
339 * Returns a new predicate that applies `f` before `self`. There is no
340 * additional short-circuiting beyond what `self` does.
341 *
342 * **Example** (Checking string length)
343 *
344 * ```ts import.meta.vitest
345 * import { Predicate } from "effect"
346 *
347 * const isLongerThan2 = Predicate.mapInput((s: string) => s.length)(
348 * (n: number) => n > 2
349 * )
350 *
351 * isLongerThan2("hello") // => true
352 * ```
353 *
354 * @see {@link Predicate}
355 * @see {@link and}
356 * @see {@link not}
357 * @category combinators
358 * @since 2.0.0
359 */
360export const mapInput: {
361 <B, A>(f: (b: B) => A): (self: Predicate<A>) => Predicate<B>
362 <A, B>(self: Predicate<A>, f: (b: B) => A): Predicate<B>
363} = dual(2, <A, B>(self: Predicate<A>, f: (b: B) => A): Predicate<B> => (b) => self(f(b)))
364
365/**
366 * Checks whether a readonly array has exactly `n` elements.
367 *
368 * **When to use**
369 *
370 * Use when you need a `Predicate` guard for exact tuple length that narrows
371 * `ReadonlyArray<T>` to `TupleOf<N, T>`.
372 *
373 * **Details**
374 *
375 * This only checks length, not element types, and returns a refinement on the
376 * array type.
377 *
378 * **Example** (Checking exact length)
379 *
380 * ```ts import.meta.vitest
381 * import { Predicate } from "effect"
382 *
383 * const isPair = Predicate.isTupleOf(2)
384 *
385 * isPair([1, 2]) // => true
386 * ```
387 *
388 * @see {@link isTupleOfAtLeast}
389 * @see {@link Tuple}
390 * @category guards
391 * @since 3.3.0
392 */
393export const isTupleOf: {
394 <N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOf<N, T>
395 <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOf<N, T>
396} = dual(2, <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOf<N, T> => self.length === n)
397
398/**
399 * Checks whether a readonly array has at least `n` elements.
400 *
401 * **When to use**
402 *
403 * Use when you need a `Predicate` guard for tuple-like minimum length that
404 * narrows `ReadonlyArray<T>` to `TupleOfAtLeast<N, T>`.
405 *
406 * **Details**
407 *
408 * This only checks length, not element types, and returns a refinement on the
409 * array type.
410 *
411 * **Example** (Checking minimum length)
412 *
413 * ```ts import.meta.vitest
414 * import { Predicate } from "effect"
415 *
416 * const hasAtLeast2 = Predicate.isTupleOfAtLeast(2)
417 *
418 * hasAtLeast2([1, 2, 3]) // => true
419 * ```
420 *
421 * @see {@link isTupleOf}
422 * @see {@link Tuple}
423 * @category guards
424 * @since 3.3.0
425 */
426export const isTupleOfAtLeast: {
427 <N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOfAtLeast<N, T>
428 <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOfAtLeast<N, T>
429} = dual(2, <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOfAtLeast<N, T> => self.length >= n)
430
431/**
432 * Checks whether a value is truthy.
433 *
434 * **When to use**
435 *
436 * Use when you want a predicate that mirrors JavaScript truthiness and filters
437 * out falsy values like `0`, `""`, and `false`.
438 *
439 * **Details**
440 *
441 * This uses `!!input` and treats `0`, `""`, `false`, `null`, and `undefined`
442 * as false.
443 *
444 * **Example** (Filtering truthy values)
445 *
446 * ```ts import.meta.vitest
447 * import { Predicate } from "effect"
448 *
449 * const values = [0, 1, "", "ok", false]
450 * const truthy = values.filter(Predicate.isTruthy) // => [1, "ok"]
451 * ```
452 *
453 * @see {@link isNullish}
454 * @see {@link isNotNullish}
455 * @category predicates
456 * @since 2.0.0
457 */
458export function isTruthy(input: unknown): boolean {
459 return !!input
460}
461
462/**
463 * Checks whether a value is a `Set`.
464 *
465 * **When to use**
466 *
467 * Use when you need a `Predicate` runtime guard for `Set` values.
468 *
469 * **Details**
470 *
471 * Uses `instanceof Set`.
472 *
473 * **Example** (Guarding a Set)
474 *
475 * ```ts import.meta.vitest
476 * import { Predicate } from "effect"
477 *
478 * const data: unknown = new Set([1, 2])
479 *
480 * if (Predicate.isSet(data)) {
481 * data.size // => 2
482 * }
483 * ```
484 *
485 * @see {@link isMap}
486 * @see {@link isIterable}
487 * @category guards
488 * @since 2.0.0
489 */
490export function isSet(input: unknown): input is Set<unknown> {
491 return input instanceof Set
492}
493
494/**
495 * Checks whether a value is a `Map`.
496 *
497 * **When to use**
498 *
499 * Use when you need a `Predicate` runtime guard for `Map` values.
500 *
501 * **Details**
502 *
503 * Uses `instanceof Map`.
504 *
505 * **Example** (Guarding a Map)
506 *
507 * ```ts import.meta.vitest
508 * import { Predicate } from "effect"
509 *
510 * const data: unknown = new Map([["a", 1]])
511 *
512 * if (Predicate.isMap(data)) {
513 * data.size // => 1
514 * }
515 * ```
516 *
517 * @see {@link isSet}
518 * @see {@link isIterable}
519 * @category guards
520 * @since 2.0.0
521 */
522export function isMap(input: unknown): input is Map<unknown, unknown> {
523 return input instanceof Map
524}
525
526/**
527 * Checks whether a value is a `string`.
528 *
529 * **When to use**
530 *
531 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
532 * string.
533 *
534 * **Details**
535 *
536 * Uses `typeof input === "string"`.
537 *
538 * **Example** (Guarding strings)
539 *
540 * ```ts import.meta.vitest
541 * import { Predicate } from "effect"
542 *
543 * const data: unknown = "hi"
544 *
545 * if (Predicate.isString(data)) {
546 * data.toUpperCase() // => "HI"
547 * }
548 * ```
549 *
550 * @see {@link isNumber}
551 * @see {@link isBoolean}
552 * @see {@link Refinement}
553 * @category guards
554 * @since 2.0.0
555 */
556export function isString(input: unknown): input is string {
557 return typeof input === "string"
558}
559
560/**
561 * Checks whether a value is a `number`.
562 *
563 * **When to use**
564 *
565 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
566 * number.
567 *
568 * **Details**
569 *
570 * Uses `typeof input === "number"` and does not exclude `NaN` or `Infinity`.
571 *
572 * **Example** (Guarding numbers)
573 *
574 * ```ts import.meta.vitest
575 * import { Predicate } from "effect"
576 *
577 * const data: unknown = 42
578 *
579 * if (Predicate.isNumber(data)) {
580 * data + 1 // => 43
581 * }
582 * ```
583 *
584 * @see {@link isBigInt}
585 * @see {@link isString}
586 * @category guards
587 * @since 2.0.0
588 */
589export function isNumber(input: unknown): input is number {
590 return typeof input === "number"
591}
592
593/**
594 * Checks whether a value is a `boolean`.
595 *
596 * **When to use**
597 *
598 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
599 * boolean.
600 *
601 * **Details**
602 *
603 * Uses `typeof input === "boolean"`.
604 *
605 * **Example** (Guarding booleans)
606 *
607 * ```ts import.meta.vitest
608 * import { Predicate } from "effect"
609 *
610 * const data: unknown = true
611 *
612 * if (Predicate.isBoolean(data)) {
613 * data ? "yes" : "no" // => "yes"
614 * }
615 * ```
616 *
617 * @see {@link isString}
618 * @see {@link isNumber}
619 * @category guards
620 * @since 2.0.0
621 */
622export function isBoolean(input: unknown): input is boolean {
623 return typeof input === "boolean"
624}
625
626/**
627 * Checks whether a value is a `bigint`.
628 *
629 * **When to use**
630 *
631 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
632 * bigint.
633 *
634 * **Details**
635 *
636 * Uses `typeof input === "bigint"`.
637 *
638 * **Example** (Guarding bigints)
639 *
640 * ```ts import.meta.vitest
641 * import { Predicate } from "effect"
642 *
643 * const data: unknown = 1n
644 *
645 * if (Predicate.isBigInt(data)) {
646 * data + 2n // => 3n
647 * }
648 * ```
649 *
650 * @see {@link isNumber}
651 * @category guards
652 * @since 2.0.0
653 */
654export function isBigInt(input: unknown): input is bigint {
655 return typeof input === "bigint"
656}
657
658/**
659 * Checks whether a value is a `symbol`.
660 *
661 * **When to use**
662 *
663 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
664 * symbol.
665 *
666 * **Details**
667 *
668 * Uses `typeof input === "symbol"`.
669 *
670 * **Example** (Guarding symbols)
671 *
672 * ```ts import.meta.vitest
673 * import { Predicate } from "effect"
674 *
675 * const data: unknown = Symbol.for("id")
676 *
677 * if (Predicate.isSymbol(data)) {
678 * data.description // => "id"
679 * }
680 * ```
681 *
682 * @see {@link isPropertyKey}
683 * @category guards
684 * @since 2.0.0
685 */
686export function isSymbol(input: unknown): input is symbol {
687 return typeof input === "symbol"
688}
689
690/**
691 * Checks whether a value is a valid `PropertyKey` (string, number, or symbol).
692 *
693 * **When to use**
694 *
695 * Use when you need a `Predicate` guard for unknown property keys before
696 * indexing.
697 *
698 * **Details**
699 *
700 * Uses `isString`, `isNumber`, and `isSymbol`.
701 *
702 * **Example** (Guarding property keys)
703 *
704 * ```ts import.meta.vitest
705 * import { Predicate } from "effect"
706 *
707 * const key: unknown = "name"
708 * const obj: Record<PropertyKey, unknown> = { name: "Ada" }
709 *
710 * if (Predicate.isPropertyKey(key) && key in obj) {
711 * obj[key] // => "Ada"
712 * }
713 * ```
714 *
715 * @see {@link isString}
716 * @see {@link isNumber}
717 * @see {@link isSymbol}
718 * @category guards
719 * @since 4.0.0
720 */
721export function isPropertyKey(u: unknown): u is PropertyKey {
722 return isString(u) || isNumber(u) || isSymbol(u)
723}
724
725/**
726 * Checks whether a value is a `function`.
727 *
728 * **When to use**
729 *
730 * Use when you need a `Predicate` guard to narrow an `unknown` value to a
731 * callable function.
732 *
733 * **Details**
734 *
735 * Uses `typeof input === "function"`.
736 *
737 * **Example** (Guarding functions)
738 *
739 * ```ts import.meta.vitest
740 * import { Predicate } from "effect"
741 *
742 * const data: unknown = () => 1
743 *
744 * if (Predicate.isFunction(data)) {
745 * data() // => 1
746 * }
747 * ```
748 *
749 * @see {@link isObjectKeyword}
750 * @category guards
751 * @since 2.0.0
752 */
753export function isFunction(input: unknown): input is Function {
754 return typeof input === "function"
755}
756
757/**
758 * Checks whether a value is `undefined`.
759 *
760 * **When to use**
761 *
762 * Use when you need a `Predicate` guard for values that are exactly
763 * `undefined`.
764 *
765 * **Details**
766 *
767 * Uses `input === undefined`.
768 *
769 * **Example** (Guarding undefined values)
770 *
771 * ```ts import.meta.vitest
772 * import { Predicate } from "effect"
773 *
774 * const data: unknown = undefined
775 *
776 * Predicate.isUndefined(data) // => true
777 * ```
778 *
779 * @see {@link isNotUndefined}
780 * @see {@link isNullish}
781 * @category guards
782 * @since 2.0.0
783 */
784export function isUndefined(input: unknown): input is undefined {
785 return input === undefined
786}
787
788/**
789 * Checks whether a value is not `undefined`.
790 *
791 * **When to use**
792 *
793 * Use when you need a `Predicate` refinement that filters out `undefined`
794 * while preserving other falsy values.
795 *
796 * **Details**
797 *
798 * Returns a refinement that excludes `undefined`.
799 *
800 * **Example** (Filtering undefined values)
801 *
802 * ```ts import.meta.vitest
803 * import { Predicate } from "effect"
804 *
805 * const values = [1, undefined, 2]
806 * const defined = values.filter(Predicate.isNotUndefined) // => [1, 2]
807 * ```
808 *
809 * @see {@link isUndefined}
810 * @see {@link isNotNullish}
811 * @category guards
812 * @since 2.0.0
813 */
814export function isNotUndefined<A>(input: A): input is Exclude<A, undefined> {
815 return input !== undefined
816}
817
818/**
819 * Checks whether a value is `null`.
820 *
821 * **When to use**
822 *
823 * Use when you need a `Predicate` guard for nullable values.
824 *
825 * **Details**
826 *
827 * Uses `input === null`.
828 *
829 * **Example** (Guarding null values)
830 *
831 * ```ts import.meta.vitest
832 * import { Predicate } from "effect"
833 *
834 * const data: unknown = null
835 *
836 * Predicate.isNull(data) // => true
837 * ```
838 *
839 * @see {@link isNotNull}
840 * @see {@link isNullish}
841 * @category guards
842 * @since 2.0.0
843 */
844export function isNull(input: unknown): input is null {
845 return input === null
846}
847
848/**
849 * Checks whether a value is not `null`.
850 *
851 * **When to use**
852 *
853 * Use when you need a `Predicate` refinement that filters out `null` while
854 * preserving other falsy values.
855 *
856 * **Details**
857 *
858 * Returns a refinement that excludes `null`.
859 *
860 * **Example** (Filtering null values)
861 *
862 * ```ts import.meta.vitest
863 * import { Predicate } from "effect"
864 *
865 * const values = [1, null, 2]
866 * const nonNull = values.filter(Predicate.isNotNull) // => [1, 2]
867 * ```
868 *
869 * @see {@link isNull}
870 * @see {@link isNotNullish}
871 * @category guards
872 * @since 2.0.0
873 */
874export function isNotNull<A>(input: A): input is Exclude<A, null> {
875 return input !== null
876}
877
878/**
879 * Checks whether a value is `null` or `undefined`.
880 *
881 * **When to use**
882 *
883 * Use when you need a `Predicate` guard for nullish values.
884 *
885 * **Details**
886 *
887 * Uses `input === null || input === undefined`.
888 *
889 * **Example** (Guarding nullish values)
890 *
891 * ```ts import.meta.vitest
892 * import { Predicate } from "effect"
893 *
894 * const values = [0, null, "", undefined]
895 * const nullish = values.filter(Predicate.isNullish) // => [null, undefined]
896 * ```
897 *
898 * @see {@link isNotNullish}
899 * @see {@link isUndefined}
900 * @see {@link isNull}
901 * @category guards
902 * @since 4.0.0
903 */
904export function isNullish<A>(input: A): input is A & (null | undefined) {
905 return input === null || input === undefined
906}
907
908/**
909 * Checks whether a value is not `null` and not `undefined`.
910 *
911 * **When to use**
912 *
913 * Use when you need a `Predicate` refinement that filters out nullish values
914 * but keeps other falsy ones.
915 *
916 * **Details**
917 *
918 * Uses `input != null`.
919 *
920 * **Example** (Filtering non-nullish values)
921 *
922 * ```ts import.meta.vitest
923 * import { Predicate } from "effect"
924 *
925 * const values = [0, null, "", undefined]
926 * const present = values.filter(Predicate.isNotNullish) // => [0, ""]
927 * ```
928 *
929 * @see {@link isNullish}
930 * @see {@link isNotNull}
931 * @see {@link isNotUndefined}
932 * @category guards
933 * @since 4.0.0
934 */
935export function isNotNullish<A>(input: A): input is NonNullable<A> {
936 return input != null
937}
938
939/**
940 * Type guard that always returns `false`.
941 *
942 * **When to use**
943 *
944 * Use when you need a `Predicate` that never accepts, e.g. in default branches.
945 *
946 * **Example** (Matching no values)
947 *
948 * ```ts import.meta.vitest
949 * import { Predicate } from "effect"
950 *
951 * Predicate.isNever("anything") // => false
952 * ```
953 *
954 * @see {@link isUnknown}
955 * @category guards
956 * @since 2.0.0
957 */
958export function isNever(_: unknown): _ is never {
959 return false
960}
961
962/**
963 * Type guard that always returns `true`.
964 *
965 * **When to use**
966 *
967 * Use when you need a `Predicate` that always accepts, e.g. as a placeholder.
968 *
969 * **Example** (Matching every value)
970 *
971 * ```ts import.meta.vitest
972 * import { Predicate } from "effect"
973 *
974 * Predicate.isUnknown(123) // => true
975 * ```
976 *
977 * @see {@link isNever}
978 * @category guards
979 * @since 2.0.0
980 */
981export function isUnknown(_: unknown): _ is unknown {
982 return true
983}
984
985/**
986 * Checks whether a value is an object or an array (non-null object).
987 *
988 * **When to use**
989 *
990 * Use when you need a `Predicate` guard that accepts plain objects and arrays,
991 * but not `null`.
992 *
993 * **Details**
994 *
995 * Uses `typeof input === "object" && input !== null` and includes arrays.
996 *
997 * **Example** (Checking objects or arrays)
998 *
999 * ```ts import.meta.vitest
1000 * import { Predicate } from "effect"
1001 *
1002 * Predicate.isObjectOrArray([]) // => true
1003 * ```
1004 *
1005 * @see {@link isObject}
1006 * @see {@link isObjectKeyword}
1007 * @category guards
1008 * @since 4.0.0
1009 */
1010export function isObjectOrArray(input: unknown): input is { [x: PropertyKey]: unknown } | Array<unknown> {
1011 return typeof input === "object" && input !== null
1012}
1013
1014/**
1015 * Checks whether a value is a non-null object value that is not an array.
1016 *
1017 * **When to use**
1018 *
1019 * Use to narrow unknown input to a non-null, non-array object with a
1020 * `Predicate` guard.
1021 *
1022 * **Details**
1023 *
1024 * This is a structural runtime check using `typeof input === "object"`, so it
1025 * also accepts object instances such as `Date`, `Map`, class instances, and
1026 * typed arrays. It excludes `null` and arrays.
1027 *
1028 * **Example** (Guarding objects)
1029 *
1030 * ```ts import.meta.vitest
1031 * import { Predicate } from "effect"
1032 *
1033 * Predicate.isObject({ a: 1 }) // => true
1034 * Predicate.isObject([1, 2]) // => false
1035 * ```
1036 *
1037 * @see {@link isObjectOrArray}
1038 * @see {@link isReadonlyObject}
1039 * @category guards
1040 * @since 2.0.0
1041 */
1042export function isObject(input: unknown): input is { [x: PropertyKey]: unknown } {
1043 return typeof input === "object" && input !== null && !Array.isArray(input)
1044}
1045
1046/**
1047 * Checks whether a value is a non-null, non-array object and narrows it to a
1048 * readonly indexable object type.
1049 *
1050 * **When to use**
1051 *
1052 * Use to narrow unknown input to a readonly view of a non-null, non-array
1053 * object with a `Predicate` guard.
1054 *
1055 * **Details**
1056 *
1057 * Readonly-ness is a TypeScript type-level view; it is not observable at
1058 * runtime. This delegates to `isObject`, so class instances and built-in object
1059 * instances are accepted.
1060 *
1061 * **Example** (Checking readonly objects)
1062 *
1063 * ```ts import.meta.vitest
1064 * import { Predicate } from "effect"
1065 *
1066 * const data: unknown = { a: 1 }
1067 *
1068 * Predicate.isReadonlyObject(data) // => true
1069 * ```
1070 *
1071 * @see {@link isObject}
1072 * @category guards
1073 * @since 4.0.0
1074 */
1075export function isReadonlyObject(input: unknown): input is { readonly [x: PropertyKey]: unknown } {
1076 return isObject(input)
1077}
1078
1079/**
1080 * Checks whether a value is an `object` in the JavaScript sense (objects, arrays, functions).
1081 *
1082 * **When to use**
1083 *
1084 * Use when you need a `Predicate` guard that accepts arrays and functions as
1085 * well as objects.
1086 *
1087 * **Details**
1088 *
1089 * Returns `true` for arrays and functions, and `false` for `null`.
1090 *
1091 * **Example** (Checking object keywords)
1092 *
1093 * ```ts import.meta.vitest
1094 * import { Predicate } from "effect"
1095 *
1096 * Predicate.isObjectKeyword(() => 1) // => true
1097 * Predicate.isObjectKeyword(null) // => false
1098 * ```
1099 *
1100 * @see {@link isObject}
1101 * @see {@link isObjectOrArray}
1102 * @category guards
1103 * @since 4.0.0
1104 */
1105export function isObjectKeyword(input: unknown): input is object {
1106 return (typeof input === "object" && input !== null) || isFunction(input)
1107}
1108
1109/**
1110 * Checks whether a value has a given property key.
1111 *
1112 * **When to use**
1113 *
1114 * Use when you need a `Predicate` guard for property access on `unknown`
1115 * values with a simple structural object check.
1116 *
1117 * **Details**
1118 *
1119 * Uses the `in` operator and `isObjectKeyword`. This does not check property
1120 * value types.
1121 *
1122 * **Example** (Guarding object properties)
1123 *
1124 * ```ts import.meta.vitest
1125 * import { Predicate } from "effect"
1126 *
1127 * const hasName = Predicate.hasProperty("name")
1128 * const data: unknown = { name: "Ada" }
1129 *
1130 * if (hasName(data)) {
1131 * data.name // => "Ada"
1132 * }
1133 * ```
1134 *
1135 * @see {@link isTagged}
1136 * @see {@link isObjectKeyword}
1137 * @category guards
1138 * @since 2.0.0
1139 */
1140export const hasProperty: {
1141 <P extends PropertyKey>(property: P): (self: unknown) => self is { [K in P]: unknown }
1142 <P extends PropertyKey>(self: unknown, property: P): self is { [K in P]: unknown }
1143} = dual(
1144 2,
1145 <P extends PropertyKey>(self: unknown, property: P): self is { [K in P]: unknown } =>
1146 isObjectKeyword(self) && (property in self)
1147)
1148
1149/**
1150 * Checks whether a value has a `_tag` property equal to the given tag.
1151 *
1152 * **When to use**
1153 *
1154 * Use when you model tagged unions with a `_tag` field and want a quick
1155 * `Predicate` guard for tagged values.
1156 *
1157 * **Details**
1158 *
1159 * Uses `hasProperty` and strict equality on `_tag`.
1160 *
1161 * **Example** (Guarding tagged values)
1162 *
1163 * ```ts import.meta.vitest
1164 * import { Predicate } from "effect"
1165 *
1166 * const isOk = Predicate.isTagged("Ok")
1167 *
1168 * isOk({ _tag: "Ok", value: 1 }) // => true
1169 * ```
1170 *
1171 * @see {@link hasProperty}
1172 * @category guards
1173 * @since 2.0.0
1174 */
1175export const isTagged: {
1176 <K extends string>(tag: K): (self: unknown) => self is { _tag: K }
1177 <K extends string>(self: unknown, tag: K): self is { _tag: K }
1178} = dual(
1179 2,
1180 <K extends string>(self: unknown, tag: K): self is { _tag: K } => hasProperty(self, "_tag") && self["_tag"] === tag
1181)
1182
1183/**
1184 * Checks whether a value is an `Error`.
1185 *
1186 * **When to use**
1187 *
1188 * Use when you need a `Predicate` guard for errors caught from unknown sources.
1189 *
1190 * **Details**
1191 *
1192 * Uses `instanceof Error`.
1193 *
1194 * **Example** (Guarding errors)
1195 *
1196 * ```ts import.meta.vitest
1197 * import { Predicate } from "effect"
1198 *
1199 * const data: unknown = new Error("boom")
1200 *
1201 * Predicate.isError(data) // => true
1202 * ```
1203 *
1204 * @see {@link isUnknown}
1205 * @category guards
1206 * @since 2.0.0
1207 */
1208export function isError(input: unknown): input is Error {
1209 return input instanceof Error
1210}
1211
1212/**
1213 * Checks whether a value is a `Uint8Array`.
1214 *
1215 * **When to use**
1216 *
1217 * Use when you need a `Predicate` runtime guard for binary data.
1218 *
1219 * **Details**
1220 *
1221 * Uses `instanceof Uint8Array`.
1222 *
1223 * **Example** (Guarding Uint8Array values)
1224 *
1225 * ```ts import.meta.vitest
1226 * import { Predicate } from "effect"
1227 *
1228 * const data: unknown = new Uint8Array([1, 2])
1229 *
1230 * Predicate.isUint8Array(data) // => true
1231 * ```
1232 *
1233 * @see {@link isIterable}
1234 * @see {@link isSet}
1235 * @category guards
1236 * @since 2.0.0
1237 */
1238export function isUint8Array(input: unknown): input is Uint8Array {
1239 return input instanceof Uint8Array
1240}
1241
1242/**
1243 * Checks whether a value is a `Date`.
1244 *
1245 * **When to use**
1246 *
1247 * Use when you need a `Predicate` runtime guard for dates.
1248 *
1249 * **Details**
1250 *
1251 * Uses `instanceof Date`.
1252 *
1253 * **Example** (Guarding Date values)
1254 *
1255 * ```ts import.meta.vitest
1256 * import { Predicate } from "effect"
1257 *
1258 * const data: unknown = new Date()
1259 *
1260 * Predicate.isDate(data) // => true
1261 * ```
1262 *
1263 * @see {@link isRegExp}
1264 * @category guards
1265 * @since 2.0.0
1266 */
1267export function isDate(input: unknown): input is Date {
1268 return input instanceof Date
1269}
1270
1271/**
1272 * Checks whether a value is iterable.
1273 *
1274 * **When to use**
1275 *
1276 * Use when you need a `Predicate` guard before iterating an unknown value.
1277 *
1278 * **Details**
1279 *
1280 * Accepts strings as iterable and uses `hasProperty` for `Symbol.iterator`.
1281 *
1282 * **Example** (Guarding iterables)
1283 *
1284 * ```ts import.meta.vitest
1285 * import { Predicate } from "effect"
1286 *
1287 * const data: unknown = [1, 2, 3]
1288 *
1289 * Predicate.isIterable(data) // => true
1290 * ```
1291 *
1292 * @see {@link isSet}
1293 * @see {@link isMap}
1294 * @category guards
1295 * @since 2.0.0
1296 */
1297export function isIterable(input: unknown): input is Iterable<unknown> {
1298 return hasProperty(input, Symbol.iterator) || isString(input)
1299}
1300
1301/**
1302 * Checks whether a value is a `Promise`-like object with `then` and `catch`.
1303 *
1304 * **When to use**
1305 *
1306 * Use when you need a `Predicate` guard for promise instances across realms.
1307 *
1308 * **Details**
1309 *
1310 * Performs a structural check for `then` and `catch` functions.
1311 *
1312 * **Example** (Guarding promises)
1313 *
1314 * ```ts import.meta.vitest
1315 * import { Predicate } from "effect"
1316 *
1317 * const data: unknown = Promise.resolve(1)
1318 *
1319 * Predicate.isPromise(data) // => true
1320 * ```
1321 *
1322 * @see {@link isPromiseLike}
1323 * @category guards
1324 * @since 2.0.0
1325 */
1326export function isPromise(input: unknown): input is Promise<unknown> {
1327 return hasProperty(input, "then") && "catch" in input && isFunction(input.then) && isFunction(input.catch)
1328}
1329
1330/**
1331 * Checks whether a value is `PromiseLike` (has a `then` method).
1332 *
1333 * **When to use**
1334 *
1335 * Use when you need a `Predicate` guard for promise-like values with a
1336 * callable `then` method.
1337 *
1338 * **Details**
1339 *
1340 * Performs a structural check for a callable `then`.
1341 *
1342 * **Example** (Guarding promise-like values)
1343 *
1344 * ```ts import.meta.vitest
1345 * import { Predicate } from "effect"
1346 *
1347 * const data: unknown = { then: () => {} }
1348 *
1349 * Predicate.isPromiseLike(data) // => true
1350 * ```
1351 *
1352 * @see {@link isPromise}
1353 * @category guards
1354 * @since 2.0.0
1355 */
1356export function isPromiseLike(input: unknown): input is PromiseLike<unknown> {
1357 return hasProperty(input, "then") && isFunction(input.then)
1358}
1359
1360/**
1361 * Checks whether a value is a `RegExp`.
1362 *
1363 * **When to use**
1364 *
1365 * Use when you need a `Predicate` runtime guard for regular expressions.
1366 *
1367 * **Details**
1368 *
1369 * Uses `instanceof RegExp`.
1370 *
1371 * **Example** (Guarding RegExp values)
1372 *
1373 * ```ts import.meta.vitest
1374 * import { Predicate } from "effect"
1375 *
1376 * const data: unknown = /abc/
1377 *
1378 * Predicate.isRegExp(data) // => true
1379 * ```
1380 *
1381 * @see {@link isDate}
1382 * @category guards
1383 * @since 3.9.0
1384 */
1385export function isRegExp(input: unknown): input is RegExp {
1386 return input instanceof RegExp
1387}
1388
1389/**
1390 * Composes two predicates or refinements into one.
1391 *
1392 * **When to use**
1393 *
1394 * Use when you want to compose two `Predicate` checks in sequence, especially
1395 * when chaining refinements for progressive narrowing.
1396 *
1397 * **Details**
1398 *
1399 * For refinements, the output type is narrowed by both checks. Evaluation
1400 * short-circuits on the first `false`.
1401 *
1402 * **Example** (Composing refinements)
1403 *
1404 * ```ts import.meta.vitest
1405 * import { Predicate } from "effect"
1406 *
1407 * const isNumber: Predicate.Refinement<unknown, number> = (u): u is number => typeof u === "number"
1408 * const isInteger: Predicate.Refinement<number, number> = (n): n is number => Number.isInteger(n)
1409 *
1410 * const isIntegerNumber = Predicate.compose(isNumber, isInteger)
1411 *
1412 * isIntegerNumber(1) // => true
1413 * ```
1414 *
1415 * @see {@link and}
1416 * @see {@link Refinement}
1417 * @category combinators
1418 * @since 2.0.0
1419 */
1420export const compose: {
1421 <A, B extends A, C extends B>(bc: Refinement<B, C>): (ab: Refinement<A, B>) => Refinement<A, C>
1422 <A, B extends A>(bc: Predicate<NoInfer<B>>): (ab: Refinement<A, B>) => Refinement<A, B>
1423 <A, B extends A, C extends B>(ab: Refinement<A, B>, bc: Refinement<B, C>): Refinement<A, C>
1424 <A, B extends A>(ab: Refinement<A, B>, bc: Predicate<NoInfer<B>>): Refinement<A, B>
1425} = dual(
1426 2,
1427 <A, B extends A, C extends B>(ab: Refinement<A, B>, bc: Refinement<B, C>): Refinement<A, C> => (a): a is C =>
1428 ab(a) && bc(a)
1429)
1430
1431/**
1432 * Creates a predicate for tuples by applying predicates to each element.
1433 *
1434 * **When to use**
1435 *
1436 * Use when you want to validate tuple positions independently by lifting
1437 * element predicates into a tuple predicate.
1438 *
1439 * **Details**
1440 *
1441 * Returns a refinement if any element predicate is a refinement. Evaluation
1442 * stops at the first failing element.
1443 *
1444 * **Example** (Checking tuples)
1445 *
1446 * ```ts import.meta.vitest
1447 * import { Predicate } from "effect"
1448 *
1449 * const tupleCheck = Predicate.Tuple([(n: number) => n > 0, Predicate.isString])
1450 *
1451 * tupleCheck([1, "ok"]) // => true
1452 * ```
1453 *
1454 * @see {@link Struct}
1455 * @see {@link isTupleOf}
1456 * @category combinators
1457 * @since 4.0.0
1458 */
1459export function Tuple<const T extends ReadonlyArray<Predicate.Any>>(
1460 elements: T
1461): [Extract<T[number], Refinement.Any>] extends [never] ? Predicate<{ readonly [I in keyof T]: Predicate.In<T[I]> }>
1462 : Refinement<
1463 { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.In<T[I]> : Predicate.In<T[I]> },
1464 { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.Out<T[I]> : Predicate.In<T[I]> }
1465 >
1466{
1467 return ((as: Array<unknown>) => {
1468 for (let i = 0; i < elements.length; i++) {
1469 if (elements[i](as[i]) === false) {
1470 return false
1471 }
1472 }
1473 return true
1474 }) as any
1475}
1476
1477/**
1478 * Creates a predicate for objects by applying predicates to named properties.
1479 *
1480 * **When to use**
1481 *
1482 * Use when you want to validate a record shape at runtime by lifting property
1483 * predicates into an object predicate.
1484 *
1485 * **Details**
1486 *
1487 * Returns a refinement if any field predicate is a refinement. Only the
1488 * specified keys are checked, and extra keys are ignored.
1489 *
1490 * **Example** (Checking structs)
1491 *
1492 * ```ts import.meta.vitest
1493 * import { Predicate } from "effect"
1494 *
1495 * const userCheck = Predicate.Struct({
1496 * id: Predicate.isNumber,
1497 * name: Predicate.isString
1498 * })
1499 *
1500 * userCheck({ id: 1, name: "Ada" }) // => true
1501 * ```
1502 *
1503 * @see {@link Tuple}
1504 * @see {@link hasProperty}
1505 * @category combinators
1506 * @since 4.0.0
1507 */
1508export function Struct<R extends Record<string, Predicate.Any>>(
1509 fields: R
1510): [Extract<R[keyof R], Refinement.Any>] extends [never] ? Predicate<{ readonly [K in keyof R]: Predicate.In<R[K]> }> :
1511 Refinement<
1512 { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.In<R[K]> : Predicate.In<R[K]> },
1513 { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.Out<R[K]> : Predicate.In<R[K]> }
1514 >
1515{
1516 const keys = Object.keys(fields)
1517 return ((a: Record<string, unknown>) => {
1518 for (const key of keys) {
1519 if (!fields[key](a[key] as never)) {
1520 return false
1521 }
1522 }
1523 return true
1524 }) as any
1525}
1526
1527/**
1528 * Negates a predicate.
1529 *
1530 * **When to use**
1531 *
1532 * Use when you want the inverse of an existing predicate.
1533 *
1534 * **Details**
1535 *
1536 * Returns a new predicate that flips the boolean result.
1537 *
1538 * **Example** (Negating a predicate)
1539 *
1540 * ```ts import.meta.vitest
1541 * import { Predicate } from "effect"
1542 *
1543 * const isNotString = Predicate.not(Predicate.isString)
1544 *
1545 * isNotString(1) // => true
1546 * ```
1547 *
1548 * @see {@link and}
1549 * @see {@link or}
1550 * @see {@link xor}
1551 * @category combinators
1552 * @since 2.0.0
1553 */
1554export function not<A>(self: Predicate<A>): Predicate<A> {
1555 return (a) => !self(a)
1556}
1557
1558/**
1559 * Creates a predicate that returns `true` if either predicate is `true`.
1560 *
1561 * **When to use**
1562 *
1563 * Use when you want to combine `Predicate`s with OR, accepting values that
1564 * satisfy at least one condition, including refinements that narrow to a union.
1565 *
1566 * **Details**
1567 *
1568 * Evaluation short-circuits on the first `true`. For refinements, the output
1569 * type is a union.
1570 *
1571 * **Example** (Checking either condition)
1572 *
1573 * ```ts import.meta.vitest
1574 * import { Predicate } from "effect"
1575 *
1576 * const isStringOrNumber = Predicate.or(Predicate.isString, Predicate.isNumber)
1577 *
1578 * isStringOrNumber("a") // => true
1579 * ```
1580 *
1581 * @see {@link and}
1582 * @see {@link xor}
1583 * @category combinators
1584 * @since 2.0.0
1585 */
1586export const or: {
1587 <A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B | C>
1588 <A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B | C>
1589 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1590 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1591} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) || that(a))
1592
1593/**
1594 * Creates a predicate that returns `true` only if both predicates are `true`.
1595 *
1596 * **When to use**
1597 *
1598 * Use when you want to combine `Predicate`s with AND, accepting values that
1599 * satisfy multiple conditions, including refinements that narrow to an
1600 * intersection.
1601 *
1602 * **Details**
1603 *
1604 * Evaluation short-circuits on the first `false`. For refinements, the output
1605 * type is an intersection.
1606 *
1607 * **Example** (Checking both conditions)
1608 *
1609 * ```ts import.meta.vitest
1610 * import { Predicate } from "effect"
1611 *
1612 * const hasAAndB = Predicate.and(
1613 * Predicate.hasProperty("a"),
1614 * Predicate.hasProperty("b")
1615 * )
1616 *
1617 * const input: unknown = JSON.parse(`{"a":1,"b":"ok"}`)
1618 * if (hasAAndB(input)) {
1619 * // input has both properties at this point
1620 * const a = input.a
1621 * const b = input.b
1622 *
1623 * const values = [a, b] // => [1, "ok"]
1624 * }
1625 * ```
1626 *
1627 * @see {@link or}
1628 * @see {@link not}
1629 * @category combinators
1630 * @since 2.0.0
1631 */
1632export const and: {
1633 <A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B & C>
1634 <A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B & C>
1635 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1636 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1637} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) && that(a))
1638
1639/**
1640 * Creates a predicate that returns `true` if exactly one predicate is `true`.
1641 *
1642 * **When to use**
1643 *
1644 * Use when you want to combine two `Predicate`s with exclusive-or semantics.
1645 *
1646 * **Details**
1647 *
1648 * Returns `true` when results differ.
1649 *
1650 * **Example** (Checking exclusive-or conditions)
1651 *
1652 * ```ts import.meta.vitest
1653 * import { Predicate } from "effect"
1654 *
1655 * const isEven = (n: number) => n % 2 === 0
1656 * const isPositive = (n: number) => n > 0
1657 * const either = Predicate.xor(isEven, isPositive)
1658 *
1659 * either(-2) // => true
1660 * ```
1661 *
1662 * @see {@link or}
1663 * @see {@link and}
1664 * @category combinators
1665 * @since 2.0.0
1666 */
1667export const xor: {
1668 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1669 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1670} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) !== that(a))
1671
1672/**
1673 * Creates a predicate that returns `true` when both predicates agree.
1674 *
1675 * **When to use**
1676 *
1677 * Use when you want to check equivalence of two `Predicate`s.
1678 *
1679 * **Details**
1680 *
1681 * Returns `true` when both results are equal.
1682 *
1683 * **Example** (Defining equivalence)
1684 *
1685 * ```ts import.meta.vitest
1686 * import { Predicate } from "effect"
1687 *
1688 * const isEven = (n: number) => n % 2 === 0
1689 * const same = Predicate.eqv(isEven, isEven)
1690 *
1691 * same(3) // => true
1692 * ```
1693 *
1694 * @see {@link xor}
1695 * @category combinators
1696 * @since 2.0.0
1697 */
1698export const eqv: {
1699 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1700 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1701} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) === that(a))
1702
1703/**
1704 * Creates a predicate representing logical implication: if `antecedent`, then `consequent`.
1705 *
1706 * **When to use**
1707 *
1708 * Use when you need to encode logical implication between `Predicate` rules,
1709 * where one rule only applies when a precondition holds.
1710 *
1711 * **Details**
1712 *
1713 * Models constraints like "if A then B" and returns `true` when the antecedent
1714 * is `false`.
1715 *
1716 * **Example** (Checking implication)
1717 *
1718 * ```ts import.meta.vitest
1719 * import { Predicate } from "effect"
1720 *
1721 * const isAdult = (age: number) => age >= 18
1722 * const canVote = (age: number) => age >= 18
1723 * const implies = Predicate.implies(isAdult, canVote)
1724 *
1725 * implies(16) // => true
1726 * ```
1727 *
1728 * @see {@link and}
1729 * @see {@link or}
1730 * @category combinators
1731 * @since 2.0.0
1732 */
1733export const implies: {
1734 <A>(consequent: Predicate<A>): (antecedent: Predicate<A>) => Predicate<A>
1735 <A>(antecedent: Predicate<A>, consequent: Predicate<A>): Predicate<A>
1736} = dual(
1737 2,
1738 <A>(antecedent: Predicate<A>, consequent: Predicate<A>): Predicate<A> => (a) => antecedent(a) ? consequent(a) : true
1739)
1740
1741/**
1742 * Creates a predicate that returns `true` when neither predicate is `true`.
1743 *
1744 * **When to use**
1745 *
1746 * Use when you want to combine two `Predicate`s with logical NOR semantics.
1747 *
1748 * **Details**
1749 *
1750 * Returns the negation of `or`.
1751 *
1752 * **Example** (Checking NOR conditions)
1753 *
1754 * ```ts import.meta.vitest
1755 * import { Predicate } from "effect"
1756 *
1757 * const neither = Predicate.nor(Predicate.isString, Predicate.isNumber)
1758 *
1759 * neither(true) // => true
1760 * ```
1761 *
1762 * @see {@link or}
1763 * @see {@link not}
1764 * @category combinators
1765 * @since 2.0.0
1766 */
1767export const nor: {
1768 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1769 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1770} = dual(
1771 2,
1772 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => !(self(a) || that(a))
1773)
1774
1775/**
1776 * Creates a predicate that returns `true` unless both predicates are `true`.
1777 *
1778 * **When to use**
1779 *
1780 * Use when you want to combine two `Predicate`s with logical NAND semantics.
1781 *
1782 * **Details**
1783 *
1784 * Returns the negation of `and`.
1785 *
1786 * **Example** (Checking NAND conditions)
1787 *
1788 * ```ts import.meta.vitest
1789 * import { Predicate } from "effect"
1790 *
1791 * const notBoth = Predicate.nand(Predicate.isString, Predicate.isNumber)
1792 *
1793 * notBoth("a") // => true
1794 * ```
1795 *
1796 * @see {@link and}
1797 * @see {@link not}
1798 * @category combinators
1799 * @since 2.0.0
1800 */
1801export const nand: {
1802 <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
1803 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
1804} = dual(
1805 2,
1806 <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => !(self(a) && that(a))
1807)
1808
1809/**
1810 * Creates a predicate that returns `true` if all predicates in the collection return `true`.
1811 *
1812 * **When to use**
1813 *
1814 * Use when you have a dynamic list of predicates to apply.
1815 *
1816 * **Details**
1817 *
1818 * Evaluation short-circuits on the first `false`. The collection is iterated
1819 * each time the predicate is called.
1820 *
1821 * **Example** (Checking all predicates)
1822 *
1823 * ```ts import.meta.vitest
1824 * import { Predicate } from "effect"
1825 *
1826 * const allChecks = Predicate.every([Predicate.isNumber, (n: number) => n > 0])
1827 *
1828 * allChecks(2) // => true
1829 * ```
1830 *
1831 * @see {@link some}
1832 * @see {@link and}
1833 * @category combining
1834 * @since 2.0.0
1835 */
1836export function every<A>(collection: Iterable<Predicate<A>>): Predicate<A> {
1837 return (a) => {
1838 for (const p of collection) {
1839 if (!p(a)) {
1840 return false
1841 }
1842 }
1843 return true
1844 }
1845}
1846
1847/**
1848 * Creates a predicate that returns `true` if any predicate in the collection returns `true`.
1849 *
1850 * **When to use**
1851 *
1852 * Use when you have a dynamic list of predicates and only need one to pass.
1853 *
1854 * **Details**
1855 *
1856 * Evaluation short-circuits on the first `true`. The collection is iterated
1857 * each time the predicate is called.
1858 *
1859 * **Example** (Checking any predicate)
1860 *
1861 * ```ts import.meta.vitest
1862 * import { Predicate } from "effect"
1863 *
1864 * const anyCheck = Predicate.some([Predicate.isString, Predicate.isNumber])
1865 *
1866 * anyCheck("ok") // => true
1867 * ```
1868 *
1869 * @see {@link every}
1870 * @see {@link or}
1871 * @category combining
1872 * @since 2.0.0
1873 */
1874export function some<A>(collection: Iterable<Predicate<A>>): Predicate<A> {
1875 return (a) => {
1876 for (const p of collection) {
1877 if (p(a)) {
1878 return true
1879 }
1880 }
1881 return false
1882 }
1883}