Skip to content
Effect Days 2026 Get your ticket

String

Works with TypeScript string values.

This module exposes common string operations in a pipe-friendly style. The helpers cover checks, comparison, concatenation, trimming, casing, slicing, padding, replacement, normalization, safe character access, search helpers that return Option, and joining strings through a reducer.

64 exports Added in v2.0.0 Source

Combining

concat

Added in v2.0.0 Source

Concatenates two strings at runtime.

Signature

declare const concat: {
<B extends string>(that: B): <A extends string>(self: A) => `${A}${B}`;
<A extends string, B extends string>(self: A, that: B): `${A}${B}`;
}

Example

(Concatenating strings)

import { pipe, String } from "effect"
String.concat("hello", "world") // => "helloworld"
pipe("hello", String.concat("world")) // => "helloworld"

Reducer for concatenating strings.

When to use

Use to concatenate many strings through APIs that consume a Reducer.

Details

The reducer starts from "", so combining an empty collection returns "".

See

  • concat for concatenating two strings directly

Signature

declare const ReducerConcat: Reducer.Reducer<string>

Comparisons

Computes locale-aware ordering for two strings, with optional locales and collator options, and returns the result as an Ordering (-1, 0, or 1).

Signature

declare function localeCompare(that: string, locales?: Array<string>, options?: CollatorOptions): (self: string) => Ordering

Example

(Comparing strings by locale)

import { pipe, String } from "effect"
pipe("a", String.localeCompare("b")) // => -1
pipe("b", String.localeCompare("a")) // => 1
pipe("a", String.localeCompare("a")) // => 0

Constants

empty

Added in v2.0.0 Source

Provides the empty string "".

When to use

Use when you need the canonical empty string value from the String module.

Signature

declare const empty: ""

Example

(Referencing the empty string)

import { String } from "effect"
String.empty // => ""
String.isEmpty(String.empty) // => true

Constructors

String

Added in v4.0.0 Source

Exposes the global string constructor.

When to use

Use to access native JavaScript string coercion or constructor behavior from the Effect module namespace.

Gotchas

Calling String(value) returns a primitive string. Calling new String(value) creates a boxed String object.

See

  • isString for checking whether a value is a primitive string

Signature

declare const String: StringConstructor

Getters

at

Added in v2.0.0 Source

Returns the character at the specified relative index safely, or None if the index is out of bounds.

Signature

declare const at: {
(index: number): (self: string) => Option<string>;
(self: string, index: number): Option<string>;
}

Example

(Accessing characters safely)

import { Option, pipe, String } from "effect"
pipe("abc", String.at(1)) // => Option.some("b")
pipe("abc", String.at(4)) // => Option.none()

charAt

Added in v2.0.0 Source

Returns the character at the specified non-negative index safely, or None if the index is out of bounds.

Signature

declare const charAt: {
(index: number): (self: string) => Option<string>;
(self: string, index: number): Option<string>;
}

Example

(Reading characters safely)

import { Option, pipe, String } from "effect"
pipe("abc", String.charAt(1)) // => Option.some("b")
pipe("abc", String.charAt(4)) // => Option.none()

charCodeAt

Added in v2.0.0 Source

Returns the character code at the specified index safely, or None if the index is out of bounds.

Signature

declare const charCodeAt: {
(index: number): (self: string) => Option<number>;
(self: string, index: number): Option<number>;
}

Example

(Reading character codes)

import { Option, String } from "effect"
String.charCodeAt("abc", 1) // => Option.some(98)
String.charCodeAt("abc", 4) // => Option.none()

codePointAt

Added in v2.0.0 Source

Returns the Unicode code point at the specified index safely, or None if the index is out of bounds.

Signature

declare const codePointAt: {
(index: number): (self: string) => Option<number>;
(self: string, index: number): Option<number>;
}

Example

(Reading code points)

import { Option, pipe, String } from "effect"
pipe("abc", String.codePointAt(1)) // => Option.some(98)
pipe("abc", String.codePointAt(10)) // => Option.none()

length

Added in v2.0.0 Source

Returns the JavaScript string length, measured in UTF-16 code units.

Signature

declare function length(self: string): number

Example

(Getting string length)

import { String } from "effect"
String.length("abc") // => 3

Guards

isEmpty

Added in v2.0.0 Source

Checks whether a string is empty.

Signature

declare function isEmpty(self: string): self is ""

Example

(Checking for empty strings)

import { String } from "effect"
String.isEmpty("") // => true
String.isEmpty("a") // => false

isString

Added in v2.0.0 Source

Checks whether a value is a string.

Signature

declare const isString: Refinement<unknown, string>

Example

(Checking for strings)

import { String } from "effect"
String.isString("a") // => true
String.isString(1) // => false

Instances

Equivalence

Added in v2.0.0 Source

Provides an Equivalence instance for strings using strict equality (===).

Signature

declare const Equivalence: Equ.Equivalence<string>

Example

(Comparing strings for equality)

import { String } from "effect"
String.Equivalence("hello", "hello") // => true
String.Equivalence("hello", "world") // => false

Order

Added in v2.0.0 Source

Provides an Order instance for comparing strings using lexicographic ordering.

Signature

declare const Order: order.Order<string>

Example

(Comparing strings lexicographically)

import { String } from "effect"
String.Order("apple", "banana") // => -1
String.Order("banana", "apple") // => 1
String.Order("apple", "apple") // => 0

Models

Concat type

Added in v2.0.0 Source

Concatenates two strings at the type level.

Signature

type Concat<A extends string, B extends string> = `${A}${B}`

Example

(Concatenating string literal types)

import type { String } from "effect"
// Type-level concatenation
type Result = String.Concat<"hello", "world"> // "helloworld"
const witness: Result = "helloworld"

Trim type

Added in v2.0.0 Source

Type-level representation of trimming whitespace from both ends of a string.

Signature

type Trim<A extends string> = TrimEnd<TrimStart<A>>

Example

(Trimming whitespace at the type level)

import type { String } from "effect"
type Result = String.Trim<" hello "> // "hello"
const witness: Result = "hello"

TrimEnd type

Added in v2.0.0 Source

Type-level representation of trimming whitespace from the end of a string.

Signature

type TrimEnd<A extends string> = A extends `${infer B}${" " | "\n" | "\t" | "\r"}` ? TrimEnd<B> : A

Example

(Trimming trailing whitespace at the type level)

import type { String } from "effect"
type Result = String.TrimEnd<"hello "> // "hello"
const witness: Result = "hello"

TrimStart type

Added in v2.0.0 Source

Type-level representation of trimming whitespace from the start of a string.

Signature

type TrimStart<A extends string> = A extends `${" " | "\n" | "\t" | "\r"}${infer B}` ? TrimStart<B> : A

Example

(Trimming leading whitespace at the type level)

import type { String } from "effect"
type Result = String.TrimStart<" hello"> // "hello"
const witness: Result = "hello"

Predicates

endsWith

Added in v2.0.0 Source

Returns true if the string ends with the specified search string.

Signature

declare function endsWith(searchString: string, position?: number): (self: string) => boolean

Example

(Checking string suffixes)

import { pipe, String } from "effect"
pipe("hello world", String.endsWith("world")) // => true
pipe("hello world", String.endsWith("hello")) // => false

includes

Added in v2.0.0 Source

Returns true if searchString appears as a substring of self, at one or more positions that are greater than or equal to position; otherwise, returns false.

Signature

declare function includes(searchString: string, position?: number): (self: string) => boolean

Example

(Checking for substrings)

import { pipe, String } from "effect"
pipe("hello world", String.includes("world")) // => true
pipe("hello world", String.includes("foo")) // => false

isNonEmpty

Added in v2.0.0 Source

Checks whether a string is non-empty.

Signature

declare function isNonEmpty(self: string): boolean

Example

(Checking for non-empty strings)

import { String } from "effect"
String.isNonEmpty("") // => false
String.isNonEmpty("a") // => true

startsWith

Added in v2.0.0 Source

Returns true if the string starts with the specified search string.

Signature

declare function startsWith(searchString: string, position?: number): (self: string) => boolean

Example

(Checking string prefixes)

import { pipe, String } from "effect"
pipe("hello world", String.startsWith("hello")) // => true
pipe("hello world", String.startsWith("world")) // => false

Searching

indexOf

Added in v2.0.0 Source

Returns the index of the first occurrence of a substring safely, or None if not found.

Signature

declare function indexOf(searchString: string): (self: string) => Option<number>

Example

(Finding the first substring index)

import { Option, pipe, String } from "effect"
pipe("abbbc", String.indexOf("b")) // => Option.some(1)
pipe("abbbc", String.indexOf("z")) // => Option.none()

lastIndexOf

Added in v2.0.0 Source

Returns the index of the last occurrence of a substring safely, or None if not found.

Signature

declare function lastIndexOf(searchString: string): (self: string) => Option<number>

Example

(Finding the last substring index)

import { Option, pipe, String } from "effect"
pipe("abbbc", String.lastIndexOf("b")) // => Option.some(3)
pipe("abbbc", String.lastIndexOf("d")) // => Option.none()

match

Added in v2.0.0 Source

Matches a string against a pattern safely and returns Option.some with the match array, or Option.none when the pattern does not match.

Signature

declare function match(regExp: string | RegExp): (self: string) => Option<RegExpMatchArray>

Example

(Matching regular expressions)

import { Option, pipe, String } from "effect"
pipe(
"hello",
String.match(/l+/),
Option.map((match) => [match[0], match.index])
) // => Option.some(["ll", 2])
pipe("hello", String.match(/x/)) // => Option.none()

matchAll

Added in v2.0.0 Source

Returns an iterator over all regular expression matches in the string using native String.prototype.matchAll semantics.

Signature

declare function matchAll(regExp: RegExp): (self: string) => IterableIterator<RegExpMatchArray>

Example

(Iterating regular expression matches)

import { pipe, String } from "effect"
const matches = pipe("hello world", String.matchAll(/l/g))
Array.from(matches, (match) => [match[0], match.index]) // => [["l", 2], ["l", 3], ["l", 9]]

Splitting

Returns an IterableIterator which yields each line contained within the string, trimming off the trailing newline character.

Signature

declare function linesIterator(self: string): LinesIterator

Example

(Iterating lines without separators)

import { String } from "effect"
Array.from(String.linesIterator("hello\nworld\n")) // => ["hello", "world"]

Returns an IterableIterator which yields each line contained within the string as well as the trailing newline character.

Signature

declare function linesWithSeparators(s: string): LinesIterator

Example

(Iterating lines with separators)

import { String } from "effect"
Array.from(String.linesWithSeparators("hello\nworld\n")) // => ["hello\n", "world\n"]

Transforming

camelCase

Added in v4.0.0 Source

Converts a string to camelCase.

When to use

Use to normalize mixed word separators or existing PascalCase/camelCase text into lower-initial camelCase identifiers.

See

  • noCase for configurable delimiters and part transforms
  • pascalCase for upper-initial PascalCase output
  • snakeCase for lowercase underscore-separated output
  • kebabCase for lowercase hyphen-separated output
  • constantCase for uppercase underscore-separated output

Signature

declare const camelCase: (self: string) => string

camelToSnake

Added in v2.0.0 Source

Converts a camelCase string to snake_case.

Signature

declare function camelToSnake(self: string): string

Example

(Converting camelCase to snake_case)

import { String } from "effect"
String.camelToSnake("helloWorld") // => "hello_world"
String.camelToSnake("fooBarBaz") // => "foo_bar_baz"

capitalize

Added in v2.0.0 Source

Capitalizes the first character of a string.

Signature

declare function capitalize<T extends string>(self: T): Capitalize<T>

Example

(Capitalizing a string)

import { pipe, String } from "effect"
pipe("abc", String.capitalize) // => "Abc"
String.capitalize("hello") // => "Hello"

configCase

Added in v4.0.0 Source

Converts a string to CONFIG_CASE (uppercase with underscores) for configuration keys.

When to use

Use to normalize configuration path segments into environment-variable-like keys while preserving numeric word groups such as v2.

Details

Unlike constantCase, digit-letter boundaries are not split. For example, "api-v2 xml" becomes "API_V2_XML".

See

  • constantCase for standard uppercase underscore-separated output

Signature

declare const configCase: (self: string) => string

constantCase

Added in v4.0.0 Source

Converts a string to CONSTANT_CASE (uppercase with underscores).

When to use

Use to normalize words from mixed input formats into uppercase, underscore-separated identifiers.

See

  • snakeCase for lowercase underscore-separated output
  • kebabCase for lowercase hyphen-separated output
  • camelCase for lower-initial camelCase output
  • pascalCase for upper-initial PascalCase output
  • configCase for configuration key casing that preserves numeric word groups
  • noCase for configurable delimiters and part transforms

Signature

declare const constantCase: (self: string) => string

kebabCase

Added in v4.0.0 Source

Converts a string to kebab-case (lowercase with hyphens).

When to use

Use to normalize free-form labels, identifiers, or keys into lowercase hyphen-separated text.

See

  • noCase for configurable delimiters and part transforms
  • snakeCase for lowercase underscore-separated output
  • constantCase for uppercase underscore-separated output
  • camelCase for lower-initial camelCase output
  • pascalCase for upper-initial PascalCase output

Signature

declare const kebabCase: (self: string) => string

kebabToSnake

Added in v2.0.0 Source

Converts a kebab-case string to snake_case.

Signature

declare function kebabToSnake(self: string): string

Example

(Converting kebab-case to snake_case)

import { String } from "effect"
String.kebabToSnake("hello-world") // => "hello_world"
String.kebabToSnake("foo-bar-baz") // => "foo_bar_baz"

noCase

Added in v4.0.0 Source

Normalizes a string by splitting it into word parts, transforming each part, and joining the parts with a configurable delimiter.

When to use

Use when you need custom word-case output with a delimiter or part transform that the fixed case helpers do not provide.

See

  • pascalCase for fixed PascalCase output
  • camelCase for fixed lower-initial camelCase output
  • constantCase for fixed uppercase underscore-separated output
  • kebabCase for fixed lowercase hyphen-separated output
  • snakeCase for fixed lowercase underscore-separated output

Signature

declare const noCase: {
(options?: {
readonly delimiter?: string;
readonly splitRegExp?: RegExp | ReadonlyArray<RegExp>;
readonly stripRegExp?: RegExp | ReadonlyArray<RegExp>;
readonly transform?: (part: string, index: number, parts: ReadonlyArray<string>) => string;
}): (self: string) => string;
(self: string, options?: {
readonly delimiter?: string;
readonly splitRegExp?: RegExp | ReadonlyArray<RegExp>;
readonly stripRegExp?: RegExp | ReadonlyArray<RegExp>;
readonly transform?: (part: string, index: number, parts: ReadonlyArray<string>) => string;
}): string;
}

normalize

Added in v2.0.0 Source

Normalizes a string according to the specified Unicode normalization form.

Signature

declare function normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD"): (self: string) => string

Example

(Normalizing Unicode strings)

import { pipe, String } from "effect"
const str = "\u1E9B\u0323"
Array.from(pipe(str, String.normalize()), (character) => character.codePointAt(0)) // => [0x1e9b, 0x323]
Array.from(pipe(str, String.normalize("NFC")), (character) => character.codePointAt(0)) // => [0x1e9b, 0x323]
Array.from(
pipe(str, String.normalize("NFD")),
(character) => character.codePointAt(0)
) // => [0x17f, 0x323, 0x307]
Array.from(pipe(str, String.normalize("NFKC")), (character) => character.codePointAt(0)) // => [0x1e69]
Array.from(
pipe(str, String.normalize("NFKD")),
(character) => character.codePointAt(0)
) // => [0x73, 0x323, 0x307]

padEnd

Added in v2.0.0 Source

Pads the string from the end with a given fill string to a specified length.

Signature

declare function padEnd(maxLength: number, fillString?: string): (self: string) => string

Example

(Padding strings at the end)

import { pipe, String } from "effect"
pipe("a", String.padEnd(5)) // => "a "
pipe("a", String.padEnd(5, "_")) // => "a____"

padStart

Added in v2.0.0 Source

Pads the string from the start with a given fill string to a specified length.

Signature

declare function padStart(maxLength: number, fillString?: string): (self: string) => string

Example

(Padding strings at the start)

import { pipe, String } from "effect"
pipe("a", String.padStart(5)) // => " a"
pipe("a", String.padStart(5, "_")) // => "____a"

pascalCase

Added in v4.0.0 Source

Converts a string to PascalCase.

When to use

Use to normalize strings from spaces, separators, or camel/Pascal word boundaries into PascalCase.

See

  • camelCase for lower-initial camelCase output
  • noCase for configurable delimiters and part transforms
  • snakeToPascal for converting known snake_case input only

Signature

declare const pascalCase: (self: string) => string

Converts a PascalCase string to snake_case.

Signature

declare function pascalToSnake(self: string): string

Example

(Converting PascalCase to snake_case)

import { String } from "effect"
String.pascalToSnake("HelloWorld") // => "hello_world"
String.pascalToSnake("FooBarBaz") // => "foo_bar_baz"

repeat

Added in v2.0.0 Source

Repeats the string the specified number of times.

Signature

declare function repeat(count: number): (self: string) => string

Example

(Repeating strings)

import { pipe, String } from "effect"
pipe("a", String.repeat(5)) // => "aaaaa"
pipe("hello", String.repeat(3)) // => "hellohellohello"

replace

Added in v2.0.0 Source

Replaces matches in a string using String.prototype.replace.

Details

String search values and non-global regular expressions replace the first match; global regular expressions replace every match.

Signature

declare function replace(searchValue: string | RegExp, replaceValue: string): (self: string) => string

Example

(Replacing a substring)

import { pipe, String } from "effect"
pipe("abc", String.replace("b", "d")) // => "adc"
pipe("hello world", String.replace("world", "Effect")) // => "hello Effect"

replaceAll

Added in v2.0.0 Source

Replaces all occurrences of a substring or pattern in a string.

Signature

declare function replaceAll(searchValue: string | RegExp, replaceValue: string): (self: string) => string

Example

(Replacing all matches)

import { pipe, String } from "effect"
pipe("ababb", String.replaceAll("b", "c")) // => "acacc"
pipe("ababb", String.replaceAll(/ba/g, "cc")) // => "accbb"

slice

Added in v2.0.0 Source

Extracts a section of a string and returns it as a new string.

Signature

declare function slice(start?: number, end?: number): (self: string) => string

Example

(Slicing strings)

import { pipe, String } from "effect"
pipe("abcd", String.slice(1, 3)) // => "bc"
pipe("hello world", String.slice(0, 5)) // => "hello"

snakeCase

Added in v4.0.0 Source

Converts a string to snake_case (lowercase with underscores).

When to use

Use to normalize mixed-case or separator-delimited text into lowercase words joined with underscores.

See

  • noCase for configurable lower-level normalization
  • kebabCase for lowercase hyphen-separated output
  • constantCase for uppercase underscore-separated output

Signature

declare const snakeCase: (self: string) => string

snakeToCamel

Added in v2.0.0 Source

Converts a snake_case string to camelCase.

Signature

declare function snakeToCamel(self: string): string

Example

(Converting snake_case to camelCase)

import { String } from "effect"
String.snakeToCamel("hello_world") // => "helloWorld"
String.snakeToCamel("foo_bar_baz") // => "fooBarBaz"

snakeToKebab

Added in v2.0.0 Source

Converts a snake_case string to kebab-case.

Signature

declare function snakeToKebab(self: string): string

Example

(Converting snake_case to kebab-case)

import { String } from "effect"
String.snakeToKebab("hello_world") // => "hello-world"
String.snakeToKebab("foo_bar_baz") // => "foo-bar-baz"

Converts a snake_case string to PascalCase.

Signature

declare function snakeToPascal(self: string): string

Example

(Converting snake_case to PascalCase)

import { String } from "effect"
String.snakeToPascal("hello_world") // => "HelloWorld"
String.snakeToPascal("foo_bar_baz") // => "FooBarBaz"

split

Added in v2.0.0 Source

Splits a string into an array of substrings using a separator.

Signature

declare const split: {
(separator: string | RegExp): (self: string) => [string, ...Array<string>];
(self: string, separator: string | RegExp): [string, ...Array<string>];
}

Example

(Splitting strings)

import { pipe, String } from "effect"
pipe("abc", String.split("")) // => ["a", "b", "c"]
pipe("", String.split("")) // => [""]
String.split("hello,world", ",") // => ["hello", "world"]

stripMargin

Added in v2.0.0 Source

Strips a leading | margin prefix from every line.

Signature

declare function stripMargin(self: string): string

Example

(Stripping pipe margins)

import { String } from "effect"
String.stripMargin(" |hello\n |world") // => "hello\nworld"

Strips a leading margin prefix from every line using the supplied margin character.

Signature

declare const stripMarginWith: {
(marginChar: string): (self: string) => string;
(self: string, marginChar: string): string;
}

Example

(Stripping custom margins)

import { String } from "effect"
String.stripMarginWith(" |hello\n |world", "|") // => "hello\nworld"

substring

Added in v2.0.0 Source

Extracts characters from a string between two specified indices.

Signature

declare function substring(start: number, end?: number): (self: string) => string

Example

(Extracting substrings)

import { pipe, String } from "effect"
pipe("abcd", String.substring(1)) // => "bcd"
pipe("abcd", String.substring(1, 3)) // => "bc"

takeLeft

Added in v2.0.0 Source

Keeps the specified number of characters from the start of a string.

Details

If n is larger than the available number of characters, the string will be returned whole.

If n is not a positive number, an empty string will be returned.

If n is a float, it will be rounded down to the nearest integer.

Signature

declare const takeLeft: {
(n: number): (self: string) => string;
(self: string, n: number): string;
}

Example

(Taking characters from the start)

import { String } from "effect"
String.takeLeft("Hello World", 5) // => "Hello"

takeRight

Added in v2.0.0 Source

Keeps the specified number of characters from the end of a string.

Details

If n is larger than the available number of characters, the string will be returned whole.

If n is not a positive number, an empty string will be returned.

If n is a float, it will be rounded down to the nearest integer.

Signature

declare const takeRight: {
(n: number): (self: string) => string;
(self: string, n: number): string;
}

Example

(Taking characters from the end)

import { String } from "effect"
String.takeRight("Hello World", 5) // => "World"

Converts the string to lowercase according to the specified locale.

Signature

declare function toLocaleLowerCase(locale?: string | Array<string>): (self: string) => string

Example

(Lowercasing strings by locale)

import { pipe, String } from "effect"
const str = "\u0130"
pipe(str, String.toLocaleLowerCase("tr")) // => "i"

Converts the string to uppercase according to the specified locale.

Signature

declare function toLocaleUpperCase(locale?: string | Array<string>): (self: string) => string

Example

(Uppercasing strings by locale)

import { pipe, String } from "effect"
const str = "i\u0307"
pipe(str, String.toLocaleUpperCase("lt-LT")) // => "I"

toLowerCase

Added in v2.0.0 Source

Converts a string to lowercase.

Signature

declare function toLowerCase<T extends string>(self: T): Lowercase<T>

Example

(Converting strings to lowercase)

import { pipe, String } from "effect"
pipe("A", String.toLowerCase) // => "a"
String.toLowerCase("HELLO") // => "hello"

toUpperCase

Added in v2.0.0 Source

Converts a string to uppercase.

Signature

declare function toUpperCase<S extends string>(self: S): Uppercase<S>

Example

(Converting strings to uppercase)

import { pipe, String } from "effect"
pipe("a", String.toUpperCase) // => "A"
String.toUpperCase("hello") // => "HELLO"

trim

Added in v2.0.0 Source

Removes whitespace from both ends of a string.

Signature

declare function trim<A extends string>(self: A): TrimEnd<TrimStart<A>>

Example

(Trimming whitespace)

import { String } from "effect"
String.trim(" a ") // => "a"
String.trim(" hello world ") // => "hello world"

trimEnd

Added in v2.0.0 Source

Removes whitespace from the end of a string.

Signature

declare function trimEnd<A extends string>(self: A): TrimEnd<A>

Example

(Trimming trailing whitespace)

import { String } from "effect"
String.trimEnd(" a ") // => " a"
String.trimEnd("hello world ") // => "hello world"

trimStart

Added in v2.0.0 Source

Removes whitespace from the start of a string.

Signature

declare function trimStart<A extends string>(self: A): TrimStart<A>

Example

(Trimming leading whitespace)

import { String } from "effect"
String.trimStart(" a ") // => "a "
String.trimStart(" hello world") // => "hello world"

uncapitalize

Added in v2.0.0 Source

Uncapitalizes the first character of a string.

Signature

declare function uncapitalize<T extends string>(self: T): Uncapitalize<T>

Example

(Uncapitalizing a string)

import { pipe, String } from "effect"
pipe("ABC", String.uncapitalize) // => "aBC"
String.uncapitalize("Hello") // => "hello"