# Predicates & Booleans

A **predicate** is just a function from a value to a boolean: `(a: A) => boolean`.
A **refinement** is a predicate that also *narrows* the TypeScript type when it
returns `true`: `(a: A) => a is B`. The `Predicate` module gives you a library of
built-in guards (for strings, numbers, objects, dates, promises, and more) plus
combinators (`and`, `or`, `not`, `compose`, `Struct`, `Tuple`) that build bigger
checks from smaller ones — crucially, while *preserving narrowing* where it makes
sense. The `Boolean` module is the companion algebra for the booleans those
predicates produce: named logical operators, a tiny branch helper (`match`), and
collection reducers.

```ts
import { Predicate } from "effect"

// A Predicate<number>: returns boolean, does NOT narrow the type
const isPositive: Predicate.Predicate<number> = (n) => n > 0

// A Refinement<unknown, string>: narrows `unknown` to `string` on success
const isString: Predicate.Refinement<unknown, string> = (u): u is string =>
  typeof u === "string"

const value: unknown = "hello"
if (isString(value)) {
  // TypeScript now knows `value` is a string here
  console.log(value.toUpperCase()) // => "HELLO"
}
```

## Common case: compose guards while keeping narrowing

The whole point of the module is that combinators keep their refinement
information. Combine the built-in guards to validate and narrow an `unknown`
value, then keep the narrowed type:

```ts
import { Predicate } from "effect"

// isObject narrows to a record; hasProperty narrows to "has key K"
const isUser = Predicate.and(
  Predicate.hasProperty("name"),
  Predicate.hasProperty("age")
)

const input: unknown = JSON.parse(`{ "name": "Ada", "age": 36 }`)

if (isUser(input)) {
  // input is narrowed to { name: unknown } & { age: unknown }
  console.log(input.name, input.age) // => Ada 36
}
```

Because guards are plain functions, they drop straight into native
`Array.prototype.filter`, and the result is narrowed too:

```ts
import { Predicate } from "effect"

const values: Array<unknown> = ["one", 2, "three", null, 4]

// strings: string[]  (filter narrows because isString is a Refinement)
const strings = values.filter(Predicate.isString)
console.log(strings) // => ["one", "three"]

// numbers: number[]
const numbers = values.filter(Predicate.isNumber)
console.log(numbers) // => [2, 4]
```

To narrow in *stages* (e.g. first check it is a number, then that it is an
integer), use [`compose`](#compose) instead of `and` — the second refinement is
applied to the already-narrowed type:

```ts
import { Predicate } from "effect"

const isInteger: Predicate.Refinement<number, number> = (n): n is number =>
  Number.isInteger(n)

// unknown -> number -> integer
const isIntegerLike = Predicate.compose(Predicate.isNumber, isInteger)

console.log(isIntegerLike(3)) // => true
console.log(isIntegerLike(3.5)) // => false
console.log(isIntegerLike("3")) // => false
```

---

# Predicate

## Types

### Predicate

`Predicate<A>` is the interface for a plain boolean check: `(a: A) => boolean`.
It never narrows on its own.

```ts
import { Predicate } from "effect"

const isEven: Predicate.Predicate<number> = (n) => n % 2 === 0

console.log(isEven(4)) // => true
console.log(isEven(5)) // => false
```

### Refinement

`Refinement<A, B extends A>` is `(a: A) => a is B`: a predicate that narrows `A`
to `B` for the TypeScript compiler when it returns `true`. Every built-in `is*`
guard is a `Refinement`.

```ts
import { Predicate } from "effect"

const isString: Predicate.Refinement<unknown, string> = (u): u is string =>
  typeof u === "string"

const x: unknown = "hi"
if (isString(x)) {
  console.log(x.length) // => 2 (x is string here)
}
```

### PredicateTypeLambda

The higher-kinded `TypeLambda` for `Predicate`, used when defining type-class
instances that abstract over predicates. Type-only; produces no runtime value.

```ts
import { Predicate } from "effect"

type TL = Predicate.PredicateTypeLambda
type P = Predicate.Predicate<number>
```

There are also type-level helpers under the `Predicate` and `Refinement`
namespaces for generic code: `Predicate.In<T>` / `Predicate.Any`, and
`Refinement.In<T>` / `Refinement.Out<T>` / `Refinement.Any`.

```ts
import { Predicate } from "effect"

type R = Predicate.Refinement<unknown, string>
type In = Predicate.Refinement.In<R> // unknown
type Out = Predicate.Refinement.Out<R> // string
```

## Primitive type guards

Each of these is a `Refinement` over `unknown` (unless noted) and narrows in
`if`/`filter`.

### isString

Narrows `unknown` to `string` via `typeof`.

```ts
import { Predicate } from "effect"

const u: unknown = "hi"
console.log(Predicate.isString(u)) // => true
console.log(Predicate.isString(42)) // => false
```

### isNumber

Narrows to `number`. Does not exclude `NaN` or `Infinity`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isNumber(42)) // => true
console.log(Predicate.isNumber(NaN)) // => true
console.log(Predicate.isNumber("42")) // => false
```

### isBoolean

Narrows to `boolean`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isBoolean(true)) // => true
console.log(Predicate.isBoolean(0)) // => false
```

### isBigInt

Narrows to `bigint`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isBigInt(1n)) // => true
console.log(Predicate.isBigInt(1)) // => false
```

### isSymbol

Narrows to `symbol`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isSymbol(Symbol.for("id"))) // => true
console.log(Predicate.isSymbol("id")) // => false
```

### isPropertyKey

Narrows to `PropertyKey` (a `string`, `number`, or `symbol`) — handy before
indexing into an object.

```ts
import { Predicate } from "effect"

const obj: Record<PropertyKey, unknown> = { name: "Ada" }
const key: unknown = "name"

if (Predicate.isPropertyKey(key) && key in obj) {
  console.log(obj[key]) // => "Ada"
}
```

### isFunction

Narrows to `Function`.

```ts
import { Predicate } from "effect"

const f: unknown = () => 1
console.log(Predicate.isFunction(f)) // => true
console.log(Predicate.isFunction({})) // => false
```

### isUndefined

Narrows to `undefined` (strict `=== undefined`).

```ts
import { Predicate } from "effect"

console.log(Predicate.isUndefined(undefined)) // => true
console.log(Predicate.isUndefined(null)) // => false
```

### isNotUndefined

Excludes `undefined` from the type: `A` becomes `Exclude<A, undefined>`. Keeps
other falsy values.

```ts
import { Predicate } from "effect"

const values = [1, undefined, 2]
console.log(values.filter(Predicate.isNotUndefined)) // => [1, 2]
```

### isNull

Narrows to `null` (strict `=== null`).

```ts
import { Predicate } from "effect"

console.log(Predicate.isNull(null)) // => true
console.log(Predicate.isNull(undefined)) // => false
```

### isNotNull

Excludes `null`: `A` becomes `Exclude<A, null>`.

```ts
import { Predicate } from "effect"

const values = [1, null, 2]
console.log(values.filter(Predicate.isNotNull)) // => [1, 2]
```

### isNullish

Narrows to `null | undefined` (matches both).

```ts
import { Predicate } from "effect"

const values = [0, null, "", undefined]
console.log(values.filter(Predicate.isNullish)) // => [null, undefined]
```

### isNotNullish

Narrows to `NonNullable<A>` — removes both `null` and `undefined` but keeps other
falsy values like `0` and `""`.

```ts
import { Predicate } from "effect"

const values = [0, null, "", undefined]
console.log(values.filter(Predicate.isNotNullish)) // => [0, ""]
```

### isNever

A refinement that always returns `false` (narrows to `never`). Useful for
exhaustiveness defaults.

```ts
import { Predicate } from "effect"

console.log(Predicate.isNever("anything")) // => false
```

### isUnknown

A refinement that always returns `true`. Useful as a placeholder predicate.

```ts
import { Predicate } from "effect"

console.log(Predicate.isUnknown(123)) // => true
```

### isObject

Narrows to a non-null object that is **not** an array. Structural `typeof` check,
so it also accepts `Date`, `Map`, and class instances.

```ts
import { Predicate } from "effect"

console.log(Predicate.isObject({ a: 1 })) // => true
console.log(Predicate.isObject([1, 2])) // => false (arrays excluded)
console.log(Predicate.isObject(null)) // => false
```

### isObjectOrArray

Narrows to a non-null object **or** array (any `typeof === "object"` that is not
`null`).

```ts
import { Predicate } from "effect"

console.log(Predicate.isObjectOrArray([])) // => true
console.log(Predicate.isObjectOrArray({ a: 1 })) // => true
console.log(Predicate.isObjectOrArray(null)) // => false
```

### isReadonlyObject

Same runtime check as `isObject`, but narrows to a `readonly` indexable object
type. Readonly-ness is type-level only.

```ts
import { Predicate } from "effect"

const data: unknown = { a: 1 }
console.log(Predicate.isReadonlyObject(data)) // => true
```

### isObjectKeyword

Narrows to the TypeScript `object` keyword — accepts objects, arrays, **and**
functions, but not `null`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isObjectKeyword(() => 1)) // => true
console.log(Predicate.isObjectKeyword([])) // => true
console.log(Predicate.isObjectKeyword(null)) // => false
```

### isTruthy

JavaScript truthiness via `!!input`, so `0`, `""`, `false`, `null`, and
`undefined` are rejected. Does not narrow to a useful type.

```ts
import { Predicate } from "effect"

console.log([0, 1, "", "ok", false].filter(Predicate.isTruthy)) // => [1, "ok"]
```

### isSet

Narrows to `Set<unknown>` via `instanceof`.

```ts
import { Predicate } from "effect"

const data: unknown = new Set([1, 2])
if (Predicate.isSet(data)) {
  console.log(data.size) // => 2
}
```

### isMap

Narrows to `Map<unknown, unknown>` via `instanceof`.

```ts
import { Predicate } from "effect"

const data: unknown = new Map([["a", 1]])
if (Predicate.isMap(data)) {
  console.log(data.size) // => 1
}
```

### isError

Narrows to `Error` via `instanceof`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isError(new Error("boom"))) // => true
console.log(Predicate.isError("boom")) // => false
```

### isUint8Array

Narrows to `Uint8Array` via `instanceof`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isUint8Array(new Uint8Array([1, 2]))) // => true
console.log(Predicate.isUint8Array([1, 2])) // => false
```

### isDate

Narrows to `Date` via `instanceof`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isDate(new Date())) // => true
console.log(Predicate.isDate("2026-01-01")) // => false
```

### isIterable

Narrows to `Iterable<unknown>` by checking for `Symbol.iterator`. Note that
strings are iterable, so they pass.

```ts
import { Predicate } from "effect"

console.log(Predicate.isIterable([1, 2, 3])) // => true
console.log(Predicate.isIterable("abc")) // => true (strings are iterable)
console.log(Predicate.isIterable(42)) // => false
```

### isPromise

Structural check (not `instanceof`): narrows to `Promise<unknown>` when the value
has callable `then` **and** `catch` methods.

```ts
import { Predicate } from "effect"

console.log(Predicate.isPromise(Promise.resolve(1))) // => true
console.log(Predicate.isPromise({ then() {} })) // => false (no `catch`)
```

### isPromiseLike

Narrows to `PromiseLike<unknown>` when the value has a callable `then` method
(does not require `catch`).

```ts
import { Predicate } from "effect"

console.log(Predicate.isPromiseLike({ then() {} })) // => true
console.log(Predicate.isPromiseLike(42)) // => false
```

### isRegExp

Narrows to `RegExp` via `instanceof`.

```ts
import { Predicate } from "effect"

console.log(Predicate.isRegExp(/abc/)) // => true
console.log(Predicate.isRegExp("abc")) // => false
```

## Structural guards

### hasProperty

Narrows an `unknown` to "has property `K`" via the `in` operator. Does not check
the value's type. Data-first and data-last.

```ts
import { Predicate } from "effect"

const hasName = Predicate.hasProperty("name")
const data: unknown = { name: "Ada" }

if (hasName(data)) {
  console.log(data.name) // => "Ada" (typed as unknown)
}
```

### isTagged

Narrows to `{ _tag: K }` — a quick structural guard for tagged unions that use a
`_tag` discriminant.

```ts
import { Predicate } from "effect"

const isOk = Predicate.isTagged("Ok")

console.log(isOk({ _tag: "Ok", value: 1 })) // => true
console.log(isOk({ _tag: "Err" })) // => false
```

### isTupleOf

Refines a `ReadonlyArray<T>` to a tuple of exactly `N` elements. Checks **length
only**, not element types. Data-first and data-last.

```ts
import { Predicate } from "effect"

const isPair = Predicate.isTupleOf(2)

console.log(isPair([1, 2])) // => true
console.log(isPair([1, 2, 3])) // => false
```

### isTupleOfAtLeast

Refines a `ReadonlyArray<T>` to a tuple of **at least** `N` elements (length
check only).

```ts
import { Predicate } from "effect"

const hasAtLeast2 = Predicate.isTupleOfAtLeast(2)

console.log(hasAtLeast2([1, 2, 3])) // => true
console.log(hasAtLeast2([1])) // => false
```

### Tuple

Lifts an array of element predicates into a single tuple predicate, checking each
position independently. If **any** element is a refinement, the result is a
refinement that narrows the whole tuple.

```ts
import { Predicate } from "effect"

const isPoint = Predicate.Tuple([Predicate.isNumber, Predicate.isString])

console.log(isPoint([1, "ok"])) // => true
console.log(isPoint([1, 2])) // => false
```

### Struct

Lifts a record of property predicates into a single object predicate, checking
only the named keys (extra keys are ignored). If any field is a refinement, the
result narrows the whole object.

```ts
import { Predicate } from "effect"

const isUser = Predicate.Struct({
  id: Predicate.isNumber,
  name: Predicate.isString
})

console.log(isUser({ id: 1, name: "Ada" })) // => true
console.log(isUser({ id: "1", name: "Ada" })) // => false
```

## Combinators

`and`, `or`, `compose`, `Tuple`, and `Struct` **preserve refinement narrowing**:
combine refinements and you still get a refinement (`and` intersects the narrowed
types, `or` unions them, `compose` chains them). The remaining combinators
(`not`, `xor`, `eqv`, `implies`, `nor`, `nand`, `every`, `some`) operate on plain
`Predicate`s and return plain `Predicate`s — they do not narrow.

### mapInput

Adapts a `Predicate<A>` to a `Predicate<B>` by mapping `B -> A` before the check.
Data-first and data-last.

```ts
import { Predicate } from "effect"

const longerThan2 = Predicate.mapInput(
  (n: number) => n > 2,
  (s: string) => s.length
)

console.log(longerThan2("hello")) // => true
console.log(longerThan2("hi")) // => false
```

### compose

Chains two refinements so the second narrows the result of the first
(`A -> B -> C`). The second argument may also be a plain `Predicate<B>`, in which
case the result is `Refinement<A, B>`. Short-circuits on the first `false`.

```ts
import { Predicate } from "effect"

const isInteger: Predicate.Refinement<number, number> = (n): n is number =>
  Number.isInteger(n)

const isIntegerLike = Predicate.compose(Predicate.isNumber, isInteger)

console.log(isIntegerLike(3)) // => true
console.log(isIntegerLike(3.5)) // => false
```

### not

Negates a predicate.

```ts
import { Predicate } from "effect"

const isNotString = Predicate.not(Predicate.isString)

console.log(isNotString(1)) // => true
console.log(isNotString("a")) // => false
```

### and

`true` only when both pass. For refinements, the output is the **intersection**
of both narrowed types. Short-circuits on the first `false`. Data-first and
data-last.

```ts
import { Predicate } from "effect"

const isPositiveInt = Predicate.and(
  Predicate.isNumber,
  (n: number) => Number.isInteger(n) && n > 0
)

console.log(isPositiveInt(3)) // => true
console.log(isPositiveInt(-3)) // => false
```

### or

`true` when either passes. For refinements, the output is the **union** of both
narrowed types. Short-circuits on the first `true`.

```ts
import { Predicate } from "effect"

// Refinement<unknown, string | number>
const isStringOrNumber = Predicate.or(Predicate.isString, Predicate.isNumber)

console.log(isStringOrNumber("a")) // => true
console.log(isStringOrNumber(true)) // => false
```

### xor

`true` when exactly one of the two predicates passes.

```ts
import { Predicate } from "effect"

const isEven = (n: number) => n % 2 === 0
const isPositive = (n: number) => n > 0
const either = Predicate.xor(isEven, isPositive)

console.log(either(-2)) // => true (even but not positive)
console.log(either(4)) // => false (both)
```

### eqv

`true` when both predicates agree (both `true` or both `false`).

```ts
import { Predicate } from "effect"

const isEven = (n: number) => n % 2 === 0
const same = Predicate.eqv(isEven, isEven)

console.log(same(3)) // => true (both false)
console.log(same(4)) // => true (both true)
```

### implies

Logical implication: if the antecedent holds, the consequent must too. Returns
`true` whenever the antecedent is `false`.

```ts
import { Predicate } from "effect"

const isAdult = (age: number) => age >= 18
const canVote = (age: number) => age >= 18
const rule = Predicate.implies(isAdult, canVote)

console.log(rule(16)) // => true (antecedent false)
console.log(rule(20)) // => true
```

### nor

`true` only when **neither** predicate passes (negation of `or`).

```ts
import { Predicate } from "effect"

const neither = Predicate.nor(Predicate.isString, Predicate.isNumber)

console.log(neither(true)) // => true
console.log(neither("a")) // => false
```

### nand

`true` unless **both** predicates pass (negation of `and`).

```ts
import { Predicate } from "effect"

const notBoth = Predicate.nand(Predicate.isString, Predicate.isNumber)

console.log(notBoth("a")) // => true
```

### every

Builds a predicate from a collection of predicates that passes only when **all**
of them pass. Short-circuits on the first `false`; re-iterates the collection on
each call.

```ts
import { Predicate } from "effect"

const allChecks = Predicate.every([Predicate.isNumber, (n: number) => n > 0])

console.log(allChecks(2)) // => true
console.log(allChecks(-2)) // => false
```

### some

Builds a predicate that passes when **any** predicate in the collection passes.
Short-circuits on the first `true`.

```ts
import { Predicate } from "effect"

const anyCheck = Predicate.some([Predicate.isString, Predicate.isNumber])

console.log(anyCheck("ok")) // => true
console.log(anyCheck(true)) // => false
```

---

# Boolean

The `Boolean` module is the algebra for the booleans your predicates produce:
named logical operators, a branch helper, ordering/equivalence instances, and
reducers. The combinators are data-first and data-last via `dual`.

<aside class="starlight-aside starlight-aside--note">
<p class="starlight-aside__title">Eager, not short-circuiting</p>
<p><code>Boolean.and</code> / <code>Boolean.or</code> evaluate plain boolean
values you already have — they are dual, eager operators, not the
short-circuiting, effectful control flow you get from <code>Effect</code>. Use
them to combine flags, not to sequence computations.</p>
</aside>

### Boolean

A re-export of the native `globalThis.Boolean` constructor for truthiness
coercion. Follows JavaScript truthiness, so non-empty strings like `"false"`
coerce to `true`.

```ts
import { Boolean } from "effect"

console.log(Boolean.Boolean(1)) // => true
console.log(Boolean.Boolean("false")) // => true (non-empty string)
console.log(Boolean.Boolean(0)) // => false
```

### isBoolean

Re-exports `Predicate.isBoolean`: narrows `unknown` to `boolean`.

```ts
import { Boolean } from "effect"

console.log(Boolean.isBoolean(true)) // => true
console.log(Boolean.isBoolean("true")) // => false
```

### Order

An `Order<boolean>` instance where `false < true`. Pass it to APIs that sort or
compare via an ordering.

```ts
import { Boolean } from "effect"

console.log(Boolean.Order(false, true)) // => -1
console.log(Boolean.Order(true, false)) // => 1
console.log(Boolean.Order(true, true)) // => 0
```

### Equivalence

An `Equivalence<boolean>` using strict equality.

```ts
import { Boolean } from "effect"

console.log(Boolean.Equivalence(true, true)) // => true
console.log(Boolean.Equivalence(true, false)) // => false
```

### match

A tiny branch helper: picks between two lazy branches based on a boolean. Cleaner
than an inline ternary when both arms are expressions. Data-first and data-last.

```ts
import { Boolean } from "effect"

const message = Boolean.match(true, {
  onFalse: () => "It's false!",
  onTrue: () => "It's true!"
})

console.log(message) // => "It's true!"
```

### not

Negates a boolean: `!self`.

```ts
import { Boolean } from "effect"

console.log(Boolean.not(true)) // => false
console.log(Boolean.not(false)) // => true
```

### and

Logical AND: `self && that`.

```ts
import { Boolean } from "effect"

console.log(Boolean.and(true, true)) // => true
console.log(Boolean.and(true, false)) // => false
```

### nand

Negated AND: `!(self && that)`.

```ts
import { Boolean } from "effect"

console.log(Boolean.nand(true, true)) // => false
console.log(Boolean.nand(true, false)) // => true
console.log(Boolean.nand(false, false)) // => true
```

### or

Logical OR: `self || that`.

```ts
import { Boolean } from "effect"

console.log(Boolean.or(false, true)) // => true
console.log(Boolean.or(false, false)) // => false
```

### nor

Negated OR — `true` only when both are `false`: `!(self || that)`.

```ts
import { Boolean } from "effect"

console.log(Boolean.nor(false, false)) // => true
console.log(Boolean.nor(true, false)) // => false
```

### xor

Exclusive OR — `true` when exactly one operand is `true`.

```ts
import { Boolean } from "effect"

console.log(Boolean.xor(true, false)) // => true
console.log(Boolean.xor(true, true)) // => false
console.log(Boolean.xor(false, false)) // => false
```

### eqv

Equivalence (XNOR) — `true` when both operands have the same value: `!xor`.

```ts
import { Boolean } from "effect"

console.log(Boolean.eqv(true, true)) // => true
console.log(Boolean.eqv(false, false)) // => true
console.log(Boolean.eqv(true, false)) // => false
```

### implies

Logical implication: `!self || that`. `true` whenever `self` is `false`.

```ts
import { Boolean } from "effect"

console.log(Boolean.implies(true, true)) // => true
console.log(Boolean.implies(true, false)) // => false
console.log(Boolean.implies(false, false)) // => true
```

### every

`true` when every boolean in an iterable is `true`. Returns `true` for an empty
iterable (matching logical AND).

```ts
import { Boolean } from "effect"

console.log(Boolean.every([true, true, true])) // => true
console.log(Boolean.every([true, false, true])) // => false
console.log(Boolean.every([])) // => true
```

### some

`true` when at least one boolean in an iterable is `true`. Returns `false` for an
empty iterable (matching logical OR).

```ts
import { Boolean } from "effect"

console.log(Boolean.some([true, false, true])) // => true
console.log(Boolean.some([false, false, false])) // => false
console.log(Boolean.some([])) // => false
```

### ReducerAnd

A `Reducer<boolean>` that combines with AND (`initialValue: true`). Pass it to
generic APIs that consume a `Reducer`; for direct iterable checks prefer
[`every`](#every). Note `combineAll` folds left-to-right and does **not**
short-circuit on `false`.

```ts
import { Boolean } from "effect"

console.log(Boolean.ReducerAnd.combineAll([true, true, false])) // => false
console.log(Boolean.ReducerAnd.combineAll([])) // => true
```

### ReducerOr

A `Reducer<boolean>` that combines with OR (`initialValue: false`). For direct
iterable checks prefer [`some`](#some).

```ts
import { Boolean } from "effect"

console.log(Boolean.ReducerOr.combineAll([false, false, true])) // => true
console.log(Boolean.ReducerOr.combineAll([])) // => false
```