Standard Library
Effect ships a small “standard library” of helpers for the JavaScript
primitives you already use every day. Each primitive type gets its own module
(String, Number, BigInt, Boolean), plus two modules for working with
functions and conditions (Function, Predicate). They are imported from the
core effect package:
import { String, Number, Boolean, BigInt, Predicate, Function } from "effect"These modules do not replace the native globals — they wrap and extend them.
Every module re-exports the global constructor under its own name, so
String.String === globalThis.String and Number.Number === globalThis.Number.
On top of that, they add data-last, pipeable, curried helpers designed to
drop into pipe / flow, and Option-returning safe variants for the many
native methods that signal failure with sentinels like -1, undefined, or
null.
import { String, Option, pipe } from "effect"
// Native sentinel: indexOf returns -1 when not found"hello".indexOf("z") // => -1
// Effect: an explicit Option insteadpipe("hello", String.indexOf("z")) // => Option.none()pipe("hello", String.indexOf("l")) // => Option.some(2)Why import the namespace
Section titled “Why import the namespace”String, Number, Boolean, and BigInt collide with TypeScript’s global
types and constructors. The Effect convention is to import the namespace and
reference members through it (String.trim, Number.sum), rather than
destructuring individual functions. This keeps call sites readable and avoids
shadowing the globals you still want available.
import { Array, String } from "effect"
// `Array` and `String` here are the Effect namespaces; the globals are still// reachable as `Array.from` / `String.fromCharCode` via the re-exported ctor.const slug = pipe("User Profile ID", String.kebabCase) // => "user-profile-id"const parts = Array.map(["a", "b"], String.toUpperCase) // => ["A", "B"]Conventions shared across these modules
Section titled “Conventions shared across these modules”A handful of patterns recur in every module here. Learn them once and they apply throughout.
- Dual (data-first / data-last) signatures. Most combinators can be called
directly (
Number.sum(2, 3)) or partially applied forpipe(pipe(2, Number.sum(3))). See Dual APIs. Option-returning safe variants vs*Unsafethrowing variants. Operations that can fail return anOption(Number.divide,String.at,BigInt.sqrt). Where a throwing counterpart exists, it is named with anUnsafesuffix (Number.divideUnsafe).- Built-in
OrderandEquivalenceinstances. Each primitive module exportsOrderandEquivalenceso the type plugs into generic sorting and comparison APIs. See Order and Equivalence. Reducer/Combinerinstances for folding. Modules expose named reducers (Number.ReducerSum,String.ReducerConcat,Boolean.ReducerAnd) for use with APIs that fold a collection through aReducerorCombiner.
The grab bag
Section titled “The grab bag”The helpers you reach for most often, across all of these modules. Each module has its own page (linked below) with the complete reference; this is the shortlist.
Build pipelines with pipe and flow
Section titled “Build pipelines with pipe and flow”import { pipe, flow, String } from "effect"
// Thread a value through steps, left to rightpipe(" Hello World ", String.trim, String.toLowerCase) // => "hello world"
// `flow` builds a reusable point-free function from the same stepsconst shout = flow(String.trim, String.toUpperCase)shout(" hi ") // => "HI"Parse and convert safely — get an Option, never NaN
Section titled “Parse and convert safely — get an Option, never NaN”import { Number, BigInt } from "effect"
Number.parse("3.14") // => Option.some(3.14)Number.parse("nope") // => Option.none()BigInt.fromString("42") // => Option.some(42n)BigInt.fromNumber(1.5) // => Option.none() (not an integer)Arithmetic and ranges that don’t surprise you
Section titled “Arithmetic and ranges that don’t surprise you”import { Number } from "effect"
Number.divide(6, 0) // => Option.none() (no Infinity)Number.clamp(15, { minimum: 0, maximum: 10 }) // => 10Number.between(5, { minimum: 0, maximum: 10 }) // => trueNumber.sumAll([1, 2, 3]) // => 6Reshape strings and convert identifier case
Section titled “Reshape strings and convert identifier case”import { String, pipe } from "effect"
String.snakeCase("User Profile ID") // => "user_profile_id"String.kebabCase("User Profile ID") // => "user-profile-id"String.camelCase("user profile id") // => "userProfileId"
pipe("a,b,c", String.split(",")) // => ["a", "b", "c"]pipe("hello", String.indexOf("l")) // => Option.some(2) (not -1)Compose type guards — and keep the narrowing
Section titled “Compose type guards — and keep the narrowing”import { Predicate } from "effect"
const isPositive = (n: number) => n > 0
// compose: narrow unknown -> number, then refine furtherconst isPosNum = Predicate.compose(Predicate.isNumber, isPositive)isPosNum(5) // => trueisPosNum("x") // => false
// and / or / not over predicates of the same inputconst isEven = (n: number) => n % 2 === 0Predicate.and(isPositive, isEven)(4) // => trueBranch on a boolean without an if
Section titled “Branch on a boolean without an if”import { Boolean } from "effect"
Boolean.match(true, { onTrue: () => "go", onFalse: () => "wait"}) // => "go"In this section
Section titled “In this section”- Function utilities —
pipe,flow,dual,compose,identity,constant,flip,tupled,memoize, and theabsurd/holeescape hatches. - String — trimming, safe character/substring access, searching, splitting, line iteration, and identifier case conversion.
- Number & BigInt — safe arithmetic, comparison
predicates, clamping, parsing, rounding,
gcd/lcm, and fold reducers. - Predicates & Booleans —
Predicatetype guards and combinators, plusBooleanalgebra andBoolean.match.