Skip to main content Link Search Menu Expand Document (external link)

Predicate.ts overview

This module provides a collection of functions for working with predicates and refinements.

A Predicate<A> is a function that takes a value of type A and returns a boolean. It is used to check if a value satisfies a certain condition.

A Refinement<A, B> is a special type of predicate that not only checks a condition but also provides a type guard, allowing TypeScript to narrow the type of the input value from A to a more specific type B within a conditional block.

The module includes:

  • Basic predicates and refinements for common types (e.g., isString, isNumber).
  • Combinators to create new predicates from existing ones (e.g., and, or, not).
  • Advanced combinators for working with data structures (e.g., tuple, struct).
  • Type-level utilities for inspecting predicate and refinement types.

Since v2.0.0


Exports Grouped by Category


combinators

and

Combines two predicates with a logical “AND”. The resulting predicate returns true only if both of the predicates return true.

If both predicates are Refinements, the resulting predicate is a Refinement to the intersection of their target types (B & C).

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

type Person = { name: string }
type Employee = { id: number }

const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"

const isPersonAndEmployee = Predicate.and(hasName, hasId)

const val: unknown = { name: "Alice", id: 123 }
if (isPersonAndEmployee(val)) {
  // val is narrowed to Person & Employee
  assert.strictEqual(val.name, "Alice")
  assert.strictEqual(val.id, 123)
}

assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name

Signature

declare const and: {
  <A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B & C>
  <A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B & C>
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

eqv

Combines two predicates with a logical “EQV” (equivalence). The resulting predicate returns true if both predicates return the same boolean value (both true or both false).

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isPositive = (n: number) => n > 0
const isEven = (n: number) => n % 2 === 0

const isPositiveEqvEven = Predicate.eqv(isPositive, isEven)

assert.strictEqual(isPositiveEqvEven(4), true) // both true -> true
assert.strictEqual(isPositiveEqvEven(3), false) // different -> false
assert.strictEqual(isPositiveEqvEven(-2), false) // different -> false
assert.strictEqual(isPositiveEqvEven(-1), true) // both false -> true

Signature

declare const eqv: {
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

implies

Creates a predicate that represents a logical “if-then” rule.

Think of it as a conditional promise: “If antecedent holds true, then I promise consequent will also be true.”

This function is invaluable for defining complex validation logic where one condition dictates another.

How It Works

The rule only fails (returns false) when the “if” part is true, but the “then” part is false. In all other cases, the promise is considered kept, and the result is true.

This includes the concept of “vacuous truth”: if the “if” part is false, the rule doesn’t apply, so the promise isn’t broken, and the result is true. (e.g., “If it rains, I’ll bring an umbrella.” If it doesn’t rain, you haven’t broken your promise, no matter what).

Key Details

  • Logical Equivalence: implies(p, q) is the same as not(p).or(q), or simply !p || q in plain JavaScript. This can be a helpful way to reason about its behavior.

  • Type-Safety Warning: This function always returns a Predicate, never a type-narrowing Refinement. A true result doesn’t guarantee the consequent passed (it could be true simply because the antecedent was false), so it cannot be used to safely narrow a type.

Example

// Rule: A user can only be an admin if they also belong to the "staff" group.
import * as assert from "node:assert"
import { Predicate } from "effect"

type User = {
  isStaff: boolean
  isAdmin: boolean
}

const isValidUserPermission = Predicate.implies(
  // antecedent: "if" the user is an admin...
  (user: User) => user.isAdmin,
  // consequent: "then" they must be staff.
  (user: User) => user.isStaff
)

// A non-admin who is not staff. Rule doesn't apply (antecedent is false).
assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: false }), true)

// A staff member who is not an admin. Rule doesn't apply (antecedent is false).
assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: false }), true)

// An admin who is also staff. The rule was followed.
assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: true }), true)

// An admin who is NOT staff. The rule was broken!
assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: true }), false)

Signature

declare const implies: {
  <A>(consequent: Predicate<A>): (antecedent: Predicate<A>) => Predicate<A>
  <A>(antecedent: Predicate<A>, consequent: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

mapInput

Transforms a Predicate<A> into a Predicate<B> by applying a function (b: B) => A to the input before passing it to the predicate. This is also known as “contramap” or “pre-composition”.

Example

import { Predicate, Number } from "effect"
import * as assert from "node:assert"

// A predicate on numbers
const isPositive: Predicate.Predicate<number> = Number.greaterThan(0)

// A function from `string` to `number`
const stringLength = (s: string): number => s.length

// Create a new predicate on strings by mapping the input
const hasPositiveLength = Predicate.mapInput(isPositive, stringLength)

assert.strictEqual(hasPositiveLength("hello"), true)
assert.strictEqual(hasPositiveLength(""), false)

Signature

declare const mapInput: {
  <B, A>(f: (b: B) => A): (self: Predicate<A>) => Predicate<B>
  <A, B>(self: Predicate<A>, f: (b: B) => A): Predicate<B>
}

Source

Since v2.0.0

nand

Combines two predicates with a logical “NAND” (negated AND). The resulting predicate returns true if at least one of the predicates returns false. This is equivalent to not(and(p, q)).

Signature

declare const nand: {
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

nor

Combines two predicates with a logical “NOR” (negated OR). The resulting predicate returns true only if both predicates return false. This is equivalent to not(or(p, q)).

Signature

declare const nor: {
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

not

Returns a new predicate that is the logical negation of the given predicate.

Note: If the input is a Refinement, the resulting predicate will be a simple Predicate, as TypeScript cannot infer the negative type.

Example

import * as assert from "node:assert"
import { Predicate, Number } from "effect"

const isNonPositive = Predicate.not(Number.greaterThan(0))

assert.strictEqual(isNonPositive(-1), true)
assert.strictEqual(isNonPositive(0), true)
assert.strictEqual(isNonPositive(1), false)

Signature

declare const not: <A>(self: Predicate<A>) => Predicate<A>

Source

Since v2.0.0

or

Combines two predicates with a logical “OR”. The resulting predicate returns true if at least one of the predicates returns true.

If both predicates are Refinements, the resulting predicate is a Refinement to the union of their target types (B | C).

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isString = (u: unknown): u is string => typeof u === "string"
const isNumber = (u: unknown): u is number => typeof u === "number"

const isStringOrNumber = Predicate.or(isString, isNumber)

assert.strictEqual(isStringOrNumber("hello"), true)
assert.strictEqual(isStringOrNumber(123), true)
assert.strictEqual(isStringOrNumber(null), false)

const value: unknown = "world"
if (isStringOrNumber(value)) {
  // value is narrowed to string | number
  console.log(value)
}

Signature

declare const or: {
  <A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B | C>
  <A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B | C>
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

xor

Combines two predicates with a logical “XOR” (exclusive OR). The resulting predicate returns true if one of the predicates returns true, but not both.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isPositive = (n: number) => n > 0
const isEven = (n: number) => n % 2 === 0

const isPositiveXorEven = Predicate.xor(isPositive, isEven)

assert.strictEqual(isPositiveXorEven(4), false) // both true -> false
assert.strictEqual(isPositiveXorEven(3), true) // one true -> true
assert.strictEqual(isPositiveXorEven(-2), true) // one true -> true
assert.strictEqual(isPositiveXorEven(-1), false) // both false -> false

Signature

declare const xor: {
  <A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
  <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A>
}

Source

Since v2.0.0

combining

all

Takes an iterable of predicates and returns a new predicate that tests an array of values. The new predicate returns true if each predicate at a given index is satisfied by the value at the same index in the array. The check stops at the length of the shorter of the two iterables (predicates or values).

See

  • tuple for a more powerful, variadic version.

Signature

declare const all: <A>(collection: Iterable<Predicate<A>>) => Predicate<ReadonlyArray<A>>

Source

Since v2.0.0

product

Combines two predicates to test a tuple of two values. The first predicate tests the first element of the tuple, and the second predicate tests the second element.

Signature

declare const product: <A, B>(self: Predicate<A>, that: Predicate<B>) => Predicate<readonly [A, B]>

Source

Since v2.0.0

productMany

Combines a predicate for a single value and an iterable of predicates for the rest of an array. Useful for checking the head and tail of an array separately.

Signature

declare const productMany: <A>(
  self: Predicate<A>,
  collection: Iterable<Predicate<A>>
) => Predicate<readonly [A, ...Array<A>]>

Source

Since v2.0.0

elements

every

Takes an iterable of predicates and returns a new predicate. The new predicate returns true if all predicates in the collection return true for a given value.

This is like Array.prototype.every but for a collection of predicates.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isPositive = (n: number) => n > 0
const isEven = (n: number) => n % 2 === 0

const isPositiveAndEven = Predicate.every([isPositive, isEven])

assert.strictEqual(isPositiveAndEven(4), true)
assert.strictEqual(isPositiveAndEven(3), false)
assert.strictEqual(isPositiveAndEven(-2), false)

See

  • some

Signature

declare const every: <A>(collection: Iterable<Predicate<A>>) => Predicate<A>

Source

Since v2.0.0

some

Takes an iterable of predicates and returns a new predicate. The new predicate returns true if at least one predicate in the collection returns true for a given value.

This is like Array.prototype.some but for a collection of predicates.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isNegative = (n: number) => n < 0
const isOdd = (n: number) => n % 2 !== 0

const isNegativeOrOdd = Predicate.some([isNegative, isOdd])

assert.strictEqual(isNegativeOrOdd(-2), true) // isNegative is true
assert.strictEqual(isNegativeOrOdd(3), true) // isOdd is true
assert.strictEqual(isNegativeOrOdd(4), false) // both are false

See

  • every

Signature

declare const some: <A>(collection: Iterable<Predicate<A>>) => Predicate<A>

Source

Since v2.0.0

guards

hasProperty

A refinement that checks if a value is an object-like value and has a specific property key.

Example

import * as assert from "node:assert"
import { hasProperty } from "effect/Predicate"

assert.strictEqual(hasProperty({ a: 1 }, "a"), true)
assert.strictEqual(hasProperty({ a: 1 }, "b"), false)

const value: unknown = { name: "Alice" }
if (hasProperty(value, "name")) {
  // The type of `value` is narrowed to `{ name: unknown }`
  // and we can safely access `value.name`
  console.log(value.name)
}

Signature

declare const hasProperty: {
  <P extends PropertyKey>(property: P): (self: unknown) => self is { [K in P]: unknown }
  <P extends PropertyKey>(self: unknown, property: P): self is { [K in P]: unknown }
}

Source

Since v2.0.0

isBigInt

A refinement that checks if a value is a bigint.

Example

import * as assert from "node:assert"
import { isBigInt } from "effect/Predicate"

assert.strictEqual(isBigInt(1n), true)

assert.strictEqual(isBigInt(1), false)
assert.strictEqual(isBigInt("1"), false)

Signature

declare const isBigInt: (input: unknown) => input is bigint

Source

Since v2.0.0

isBoolean

A refinement that checks if a value is a boolean.

Example

import * as assert from "node:assert"
import { isBoolean } from "effect/Predicate"

assert.strictEqual(isBoolean(true), true)
assert.strictEqual(isBoolean(false), true)

assert.strictEqual(isBoolean("true"), false)
assert.strictEqual(isBoolean(0), false)

Signature

declare const isBoolean: (input: unknown) => input is boolean

Source

Since v2.0.0

isDate

A refinement that checks if a value is a Date object.

Example

import * as assert from "node:assert"
import { isDate } from "effect/Predicate"

assert.strictEqual(isDate(new Date()), true)

assert.strictEqual(isDate(Date.now()), false) // `Date.now()` returns a number
assert.strictEqual(isDate("2023-01-01"), false)

Signature

declare const isDate: (input: unknown) => input is Date

Source

Since v2.0.0

isError

A refinement that checks if a value is an instance of Error.

Example

import * as assert from "node:assert"
import { isError } from "effect/Predicate"

assert.strictEqual(isError(new Error("boom")), true)
assert.strictEqual(isError(new TypeError("boom")), true)

assert.strictEqual(isError({ message: "boom" }), false)
assert.strictEqual(isError("boom"), false)

Signature

declare const isError: (input: unknown) => input is Error

Source

Since v2.0.0

isFunction

A refinement that checks if a value is a Function.

Example

import * as assert from "node:assert"
import { isFunction } from "effect/Predicate"

assert.strictEqual(
  isFunction(() => {}),
  true
)
assert.strictEqual(isFunction(isFunction), true)

assert.strictEqual(isFunction("function"), false)

Signature

declare const isFunction: (input: unknown) => input is Function

Source

Since v2.0.0

isIterable

A refinement that checks if a value is an Iterable. Many built-in types are iterable, such as Array, string, Map, and Set.

Example

import * as assert from "node:assert"
import { isIterable } from "effect/Predicate"

assert.strictEqual(isIterable([]), true)
assert.strictEqual(isIterable("hello"), true)
assert.strictEqual(isIterable(new Set()), true)

assert.strictEqual(isIterable({}), false)
assert.strictEqual(isIterable(123), false)

Signature

declare const isIterable: (input: unknown) => input is Iterable<unknown>

Source

Since v2.0.0

isMap

A refinement that checks if a value is a Map.

Example

import * as assert from "node:assert"
import { isMap } from "effect/Predicate"

assert.strictEqual(isMap(new Map()), true)

assert.strictEqual(isMap({}), false)
assert.strictEqual(isMap(new Set()), false)

Signature

declare const isMap: (input: unknown) => input is Map<unknown, unknown>

Source

Since v2.0.0

isNever

A refinement that always returns false. The type is narrowed to never.

Example

import * as assert from "node:assert"
import { isNever } from "effect/Predicate"

assert.strictEqual(isNever(1), false)
assert.strictEqual(isNever(null), false)
assert.strictEqual(isNever({}), false)

Signature

declare const isNever: (input: unknown) => input is never

Source

Since v2.0.0

isNotNull

A refinement that checks if a value is not null.

Example

import * as assert from "node:assert"
import { isNotNull } from "effect/Predicate"

assert.strictEqual(isNotNull(undefined), true)
assert.strictEqual(isNotNull("value"), true)

assert.strictEqual(isNotNull(null), false)

Signature

declare const isNotNull: <A>(input: A) => input is Exclude<A, null>

Source

Since v2.0.0

isNotNullable

A refinement that checks if a value is neither null nor undefined. The type is narrowed to NonNullable<A>.

Example

import * as assert from "node:assert"
import { isNotNullable } from "effect/Predicate"

assert.strictEqual(isNotNullable(0), true)
assert.strictEqual(isNotNullable("hello"), true)

assert.strictEqual(isNotNullable(null), false)
assert.strictEqual(isNotNullable(undefined), false)

See

  • isNullable

Signature

declare const isNotNullable: <A>(input: A) => input is NonNullable<A>

Source

Since v2.0.0

isNotUndefined

A refinement that checks if a value is not undefined.

Example

import * as assert from "node:assert"
import { isNotUndefined } from "effect/Predicate"

assert.strictEqual(isNotUndefined(null), true)
assert.strictEqual(isNotUndefined("value"), true)

assert.strictEqual(isNotUndefined(undefined), false)

Signature

declare const isNotUndefined: <A>(input: A) => input is Exclude<A, undefined>

Source

Since v2.0.0

isNull

A refinement that checks if a value is null.

Example

import * as assert from "node:assert"
import { isNull } from "effect/Predicate"

assert.strictEqual(isNull(null), true)

assert.strictEqual(isNull(undefined), false)
assert.strictEqual(isNull("null"), false)

Signature

declare const isNull: (input: unknown) => input is null

Source

Since v2.0.0

isNullable

A refinement that checks if a value is either null or undefined.

Example

import * as assert from "node:assert"
import { isNullable } from "effect/Predicate"

assert.strictEqual(isNullable(null), true)
assert.strictEqual(isNullable(undefined), true)

assert.strictEqual(isNullable(0), false)
assert.strictEqual(isNullable(""), false)

See

  • isNotNullable

Signature

declare const isNullable: <A>(input: A) => input is Extract<A, null | undefined>

Source

Since v2.0.0

isNumber

A refinement that checks if a value is a number. Note that this check returns false for NaN.

Example

import * as assert from "node:assert"
import { isNumber } from "effect/Predicate"

assert.strictEqual(isNumber(123), true)
assert.strictEqual(isNumber(0), true)
assert.strictEqual(isNumber(-1.5), true)

assert.strictEqual(isNumber("123"), false)
assert.strictEqual(isNumber(NaN), false) // Special case: NaN is a number type but returns false

Signature

declare const isNumber: (input: unknown) => input is number

Source

Since v2.0.0

isObject

A refinement that checks if a value is an object. Note that in JavaScript, arrays and functions are also considered objects.

Example

import * as assert from "node:assert"
import { isObject } from "effect/Predicate"

assert.strictEqual(isObject({}), true)
assert.strictEqual(isObject([]), true)
assert.strictEqual(
  isObject(() => {}),
  true
)

assert.strictEqual(isObject(null), false)
assert.strictEqual(isObject("hello"), false)

See

  • isRecord to check for plain objects (excluding arrays and functions).

Signature

declare const isObject: (input: unknown) => input is object

Source

Since v2.0.0

isPromise

A refinement that checks if a value is a Promise. It performs a duck-typing check for .then and .catch methods.

Example

import * as assert from "node:assert"
import { isPromise } from "effect/Predicate"

assert.strictEqual(isPromise(Promise.resolve(1)), true)
assert.strictEqual(isPromise(new Promise(() => {})), true)

assert.strictEqual(isPromise({ then() {} }), false) // Missing .catch
assert.strictEqual(isPromise({}), false)

See

  • isPromiseLike

Signature

declare const isPromise: (input: unknown) => input is Promise<unknown>

Source

Since v2.0.0

isPromiseLike

A refinement that checks if a value is PromiseLike. It performs a duck-typing check for a .then method.

Example

import * as assert from "node:assert"
import { isPromiseLike } from "effect/Predicate"

assert.strictEqual(isPromiseLike(Promise.resolve(1)), true)
assert.strictEqual(isPromiseLike({ then: () => {} }), true)

assert.strictEqual(isPromiseLike({}), false)

See

  • isPromise

Signature

declare const isPromiseLike: (input: unknown) => input is PromiseLike<unknown>

Source

Since v2.0.0

isReadonlyRecord

A refinement that checks if a value is a readonly record (i.e., a plain object). This check returns false for arrays, null, and functions.

This is an alias for isRecord.

Example

import * as assert from "node:assert"
import { isReadonlyRecord } from "effect/Predicate"

assert.strictEqual(isReadonlyRecord({}), true)
assert.strictEqual(isReadonlyRecord({ a: 1 }), true)

assert.strictEqual(isReadonlyRecord([]), false)
assert.strictEqual(isReadonlyRecord(null), false)

Signature

declare const isReadonlyRecord: (input: unknown) => input is { readonly [x: string | symbol]: unknown }

Source

Since v2.0.0

isRecord

A refinement that checks if a value is a record (i.e., a plain object). This check returns false for arrays, null, and functions.

Example

import * as assert from "node:assert"
import { isRecord } from "effect/Predicate"

assert.strictEqual(isRecord({}), true)
assert.strictEqual(isRecord({ a: 1 }), true)

assert.strictEqual(isRecord([]), false)
assert.strictEqual(isRecord(new Date()), false)
assert.strictEqual(isRecord(null), false)
assert.strictEqual(
  isRecord(() => null),
  false
)

See

  • isObject

Signature

declare const isRecord: (input: unknown) => input is { [x: string | symbol]: unknown }

Source

Since v2.0.0

isRegExp

A refinement that checks if a value is a RegExp.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

assert.strictEqual(Predicate.isRegExp(/a/), true)
assert.strictEqual(Predicate.isRegExp(new RegExp("a")), true)

assert.strictEqual(Predicate.isRegExp("/a/"), false)

Signature

declare const isRegExp: (input: unknown) => input is RegExp

Source

Since v3.9.0

isSet

A refinement that checks if a value is a Set.

Example

import * as assert from "node:assert"
import { isSet } from "effect/Predicate"

assert.strictEqual(isSet(new Set([1, 2])), true)
assert.strictEqual(isSet(new Set()), true)

assert.strictEqual(isSet({}), false)
assert.strictEqual(isSet([1, 2]), false)

Signature

declare const isSet: (input: unknown) => input is Set<unknown>

Source

Since v2.0.0

isString

A refinement that checks if a value is a string.

Example

import * as assert from "node:assert"
import { isString } from "effect/Predicate"

assert.strictEqual(isString("hello"), true)
assert.strictEqual(isString(""), true)

assert.strictEqual(isString(123), false)
assert.strictEqual(isString(null), false)

Signature

declare const isString: (input: unknown) => input is string

Source

Since v2.0.0

isSymbol

A refinement that checks if a value is a symbol.

Example

import * as assert from "node:assert"
import { isSymbol } from "effect/Predicate"

assert.strictEqual(isSymbol(Symbol.for("a")), true)

assert.strictEqual(isSymbol("a"), false)

Signature

declare const isSymbol: (input: unknown) => input is symbol

Source

Since v2.0.0

isTagged

A refinement that checks if a value is an object with a _tag property that matches the given tag. This is a powerful tool for working with discriminated union types.

Example

import * as assert from "node:assert"
import { isTagged } from "effect/Predicate"

type Shape = { _tag: "circle"; radius: number } | { _tag: "square"; side: number }

const isCircle = isTagged("circle")

const shape1: Shape = { _tag: "circle", radius: 10 }
const shape2: Shape = { _tag: "square", side: 5 }

assert.strictEqual(isCircle(shape1), true)
assert.strictEqual(isCircle(shape2), false)

if (isCircle(shape1)) {
  // shape1 is now narrowed to { _tag: "circle"; radius: number }
  assert.strictEqual(shape1.radius, 10)
}

Signature

declare const isTagged: {
  <K extends string>(tag: K): (self: unknown) => self is { _tag: K }
  <K extends string>(self: unknown, tag: K): self is { _tag: K }
}

Source

Since v2.0.0

isTruthy

A predicate that checks if a value is “truthy” in JavaScript. Fails for false, 0, -0, 0n, "", null, undefined, and NaN.

Example

import * as assert from "node:assert"
import { isTruthy } from "effect/Predicate"

assert.strictEqual(isTruthy(1), true)
assert.strictEqual(isTruthy("hello"), true)
assert.strictEqual(isTruthy({}), true)

assert.strictEqual(isTruthy(0), false)
assert.strictEqual(isTruthy(""), false)
assert.strictEqual(isTruthy(null), false)
assert.strictEqual(isTruthy(undefined), false)

Signature

declare const isTruthy: (input: unknown) => boolean

Source

Since v2.0.0

isTupleOf

A refinement that checks if a ReadonlyArray<T> is a tuple with exactly N elements. If the check is successful, the type is narrowed to TupleOf<N, T>.

Example

import * as assert from "node:assert"
import { isTupleOf } from "effect/Predicate"

const isTupleOf3 = isTupleOf(3)

assert.strictEqual(isTupleOf3([1, 2, 3]), true)
assert.strictEqual(isTupleOf3([1, 2]), false)

const arr: number[] = [1, 2, 3]
if (isTupleOf(arr, 3)) {
  // The type of arr is now [number, number, number]
  const [a, b, c] = arr
  assert.deepStrictEqual([a, b, c], [1, 2, 3])
}

Signature

declare const isTupleOf: {
  <N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOf<N, T>
  <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOf<N, T>
}

Source

Since v3.3.0

isTupleOfAtLeast

A refinement that checks if a ReadonlyArray<T> is a tuple with at least N elements. If the check is successful, the type is narrowed to TupleOfAtLeast<N, T>.

Example

import * as assert from "node:assert"
import { isTupleOfAtLeast } from "effect/Predicate"

const isTupleOfAtLeast3 = isTupleOfAtLeast(3)

assert.strictEqual(isTupleOfAtLeast3([1, 2, 3]), true)
assert.strictEqual(isTupleOfAtLeast3([1, 2, 3, 4]), true)
assert.strictEqual(isTupleOfAtLeast3([1, 2]), false)

const arr: number[] = [1, 2, 3, 4]
if (isTupleOfAtLeast(arr, 3)) {
  // The type of arr is now [number, number, number, ...number[]]
  const [a, b, c] = arr
  assert.deepStrictEqual([a, b, c], [1, 2, 3])
}

Signature

declare const isTupleOfAtLeast: {
  <N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOfAtLeast<N, T>
  <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOfAtLeast<N, T>
}

Source

Since v3.3.0

isUint8Array

A refinement that checks if a value is a Uint8Array.

Example

import * as assert from "node:assert"
import { isUint8Array } from "effect/Predicate"

assert.strictEqual(isUint8Array(new Uint8Array()), true)

assert.strictEqual(isUint8Array(new Uint16Array()), false)
assert.strictEqual(isUint8Array([1, 2, 3]), false)

Signature

declare const isUint8Array: (input: unknown) => input is Uint8Array

Source

Since v2.0.0

isUndefined

A refinement that checks if a value is undefined.

Example

import * as assert from "node:assert"
import { isUndefined } from "effect/Predicate"

assert.strictEqual(isUndefined(undefined), true)

assert.strictEqual(isUndefined(null), false)
assert.strictEqual(isUndefined("undefined"), false)

Signature

declare const isUndefined: (input: unknown) => input is undefined

Source

Since v2.0.0

isUnknown

A refinement that always returns true. The type is narrowed to unknown.

Example

import * as assert from "node:assert"
import { isUnknown } from "effect/Predicate"

assert.strictEqual(isUnknown(1), true)
assert.strictEqual(isUnknown(null), true)
assert.strictEqual(isUnknown({}), true)

Signature

declare const isUnknown: (input: unknown) => input is unknown

Source

Since v2.0.0

models

Predicate (interface)

Represents a function that takes a value of type A and returns true if the value satisfies some condition, false otherwise.

Example

import { Predicate } from "effect"
import * as assert from "node:assert"

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

assert.strictEqual(isEven(2), true)
assert.strictEqual(isEven(3), false)

Signature

export interface Predicate<in A> {
  (a: A): boolean
}

Source

Since v2.0.0

Refinement (interface)

Represents a function that serves as a type guard.

A Refinement<A, B> is a function that takes a value of type A and returns a type predicate a is B, where B is a subtype of A. If the function returns true, TypeScript will narrow the type of the input variable to B.

Example

import { Predicate } from "effect"
import * as assert from "node:assert"

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

const value: unknown = "hello"

if (isString(value)) {
  // value is now known to be a string
  assert.strictEqual(value.toUpperCase(), "HELLO")
}

Signature

export interface Refinement<in A, out B extends A> {
  (a: A): a is B
}

Source

Since v2.0.0

type lambdas

PredicateTypeLambda (interface)

A TypeLambda for Predicate. This is used to support higher-kinded types and allows Predicate to be used in generic contexts within the effect ecosystem.

Signature

export interface PredicateTypeLambda extends TypeLambda {
  readonly type: Predicate<this["Target"]>
}

Source

Since v2.0.0

type-level

Predicate (namespace)

A namespace for type-level utilities for Predicate.

Source

Since v3.6.0

In (type alias)

Extracts the input type A from a Predicate<A>.

Example

import { type Predicate } from "effect"

type T = Predicate.Predicate.In<Predicate.Predicate<string>> // T is string

Signature

type In<T> = [T] extends [Predicate<infer _A>] ? _A : never

Source

Since v3.6.0

Any (type alias)

A type representing any Predicate.

Signature

type Any = Predicate<never>

Source

Since v3.6.0

Refinement (namespace)

A namespace for type-level utilities for Refinement.

Source

Since v3.6.0

In (type alias)

Extracts the input type A from a Refinement<A, B>.

Example

import { type Predicate } from "effect"

type IsString = Predicate.Refinement<unknown, string>
type T = Predicate.Refinement.In<IsString> // T is unknown

Signature

type In<T> = [T] extends [Refinement<infer _A, infer _>] ? _A : never

Source

Since v3.6.0

Out (type alias)

Extracts the output (refined) type B from a Refinement<A, B>.

Example

import { type Predicate } from "effect"

type IsString = Predicate.Refinement<unknown, string>
type T = Predicate.Refinement.Out<IsString> // T is string

Signature

type Out<T> = [T] extends [Refinement<infer _, infer _B>] ? _B : never

Source

Since v3.6.0

Any (type alias)

A type representing any Refinement.

Signature

type Any = Refinement<any, any>

Source

Since v3.6.0

utils

compose

Composes a Refinement with another Refinement or Predicate.

This can be used to chain checks. The first refinement is applied, and if it passes, the second check is applied to the same value, potentially refining the type further.

Example

import { Predicate } from "effect"
import * as assert from "node:assert"

const isString = (u: unknown): u is string => typeof u === "string"
const minLength =
  (n: number) =>
  (s: string): boolean =>
    s.length >= n

// Create a refinement that checks for a string with a minimum length of 3
const isLongString = Predicate.compose(isString, minLength(3))

let value: unknown = "hello"

assert.strictEqual(isLongString(value), true)
if (isLongString(value)) {
  // value is narrowed to string
  assert.strictEqual(value.toUpperCase(), "HELLO")
}
assert.strictEqual(isLongString("hi"), false)

Signature

declare const compose: {
  <A, B extends A, C extends B, D extends C>(bc: Refinement<C, D>): (ab: Refinement<A, B>) => Refinement<A, D>
  <A, B extends A>(bc: Predicate<NoInfer<B>>): (ab: Refinement<A, B>) => Refinement<A, B>
  <A, B extends A, C extends B, D extends C>(ab: Refinement<A, B>, bc: Refinement<C, D>): Refinement<A, D>
  <A, B extends A>(ab: Refinement<A, B>, bc: Predicate<NoInfer<B>>): Refinement<A, B>
}

Source

Since v2.0.0

struct

Combines a record of predicates into a single predicate that tests a record of values. This function is highly type-aware and will produce a Refinement if any of the provided predicates are Refinements, allowing for powerful type-narrowing of structs.

  • If all predicates are Predicate<T>, the result is Predicate<{ k: T, ... }>.
  • If any predicate is a Refinement<A, B>, the result is a Refinement that narrows the input record type to a more specific record type.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isString = (u: unknown): u is string => typeof u === "string"
const isNumber = (u: unknown): u is number => typeof u === "number"

const personPredicate = Predicate.struct({
  name: isString,
  age: isNumber
})

const value: { name: unknown; age: unknown } = { name: "Alice", age: 30 }
if (personPredicate(value)) {
  // value is narrowed to { name: string; age: number }
  assert.strictEqual(value.name.toUpperCase(), "ALICE")
  assert.strictEqual(value.age.toFixed(0), "30")
}
assert.strictEqual(personPredicate({ name: "Bob", age: "40" }), false)

Signature

declare const struct: <R extends Record<string, Predicate.Any>>(
  fields: R
) => [Extract<R[keyof R], Refinement.Any>] extends [never]
  ? Predicate<{ readonly [K in keyof R]: Predicate.In<R[K]> }>
  : Refinement<
      { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.In<R[K]> : Predicate.In<R[K]> },
      { readonly [K in keyof R]: R[K] extends Refinement.Any ? Refinement.Out<R[K]> : Predicate.In<R[K]> }
    >

Source

Since v2.0.0

tuple

Combines an array of predicates into a single predicate that tests an array of values. This function is highly type-aware and will produce a Refinement if any of the provided predicates are Refinements, allowing for powerful type-narrowing of tuples.

  • If all predicates are Predicate<T>, the result is Predicate<[T, T, ...]>.
  • If any predicate is a Refinement<A, B>, the result is a Refinement that narrows the input tuple type to a more specific tuple type.

Example

import * as assert from "node:assert"
import { Predicate } from "effect"

const isString = (u: unknown): u is string => typeof u === "string"
const isNumber = (u: unknown): u is number => typeof u === "number"

// Create a refinement for a [string, number] tuple
const isStringNumberTuple = Predicate.tuple(isString, isNumber)

const value: [unknown, unknown] = ["hello", 123]
if (isStringNumberTuple(value)) {
  // value is narrowed to [string, number]
  const [s, n] = value
  assert.strictEqual(s.toUpperCase(), "HELLO")
  assert.strictEqual(n.toFixed(2), "123.00")
}
assert.strictEqual(isStringNumberTuple(["hello", "123"]), false)

Signature

declare const tuple: <T extends ReadonlyArray<Predicate.Any>>(
  ...elements: T
) => [Extract<T[number], Refinement.Any>] extends [never]
  ? Predicate<{ readonly [I in keyof T]: Predicate.In<T[I]> }>
  : Refinement<
      { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.In<T[I]> : Predicate.In<T[I]> },
      { readonly [I in keyof T]: T[I] extends Refinement.Any ? Refinement.Out<T[I]> : Predicate.In<T[I]> }
    >

Source

Since v2.0.0