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.
Combining
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"ReducerConcat
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
localeCompare
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) => OrderingExample
(Comparing strings by locale)
import { pipe, String } from "effect"
pipe("a", String.localeCompare("b")) // => -1pipe("b", String.localeCompare("a")) // => 1pipe("a", String.localeCompare("a")) // => 0Constants
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) // => trueConstructors
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: StringConstructorGetters
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()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
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
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()Returns the JavaScript string length, measured in UTF-16 code units.
Signature
declare function length(self: string): numberExample
(Getting string length)
import { String } from "effect"
String.length("abc") // => 3Guards
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("") // => trueString.isEmpty("a") // => falseChecks whether a value is a string.
Signature
declare const isString: Refinement<unknown, string>Example
(Checking for strings)
import { String } from "effect"
String.isString("a") // => trueString.isString(1) // => falseInstances
Equivalence
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") // => trueString.Equivalence("hello", "world") // => falseProvides 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") // => -1String.Order("banana", "apple") // => 1String.Order("apple", "apple") // => 0Models
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 concatenationtype Result = String.Concat<"hello", "world"> // "helloworld"
const witness: Result = "helloworld"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"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> : AExample
(Trimming trailing whitespace at the type level)
import type { String } from "effect"
type Result = String.TrimEnd<"hello "> // "hello"
const witness: Result = "hello"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> : AExample
(Trimming leading whitespace at the type level)
import type { String } from "effect"
type Result = String.TrimStart<" hello"> // "hello"
const witness: Result = "hello"Predicates
Returns true if the string ends with the specified search string.
Signature
declare function endsWith(searchString: string, position?: number): (self: string) => booleanExample
(Checking string suffixes)
import { pipe, String } from "effect"
pipe("hello world", String.endsWith("world")) // => truepipe("hello world", String.endsWith("hello")) // => falseReturns 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) => booleanExample
(Checking for substrings)
import { pipe, String } from "effect"
pipe("hello world", String.includes("world")) // => truepipe("hello world", String.includes("foo")) // => falseisNonEmpty
Checks whether a string is non-empty.
Signature
declare function isNonEmpty(self: string): booleanExample
(Checking for non-empty strings)
import { String } from "effect"
String.isNonEmpty("") // => falseString.isNonEmpty("a") // => truestartsWith
Returns true if the string starts with the specified search string.
Signature
declare function startsWith(searchString: string, position?: number): (self: string) => booleanExample
(Checking string prefixes)
import { pipe, String } from "effect"
pipe("hello world", String.startsWith("hello")) // => truepipe("hello world", String.startsWith("world")) // => falseSearching
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
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()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()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]]Returns the index of the first match for a string or regular expression safely, or
Option.none when no match is found.
Signature
declare const search: { (regExp: string | RegExp): (self: string) => Option<number>; (self: string, regExp: string | RegExp): Option<number>;}Example
(Searching strings)
import { Option, String } from "effect"
String.search("ababb", "b") // => Option.some(1)String.search("ababb", /abb/) // => Option.some(2)String.search("ababb", "d") // => Option.none()Splitting
linesIterator
Returns an IterableIterator which yields each line contained within the
string, trimming off the trailing newline character.
Signature
declare function linesIterator(self: string): LinesIteratorExample
(Iterating lines without separators)
import { String } from "effect"
Array.from(String.linesIterator("hello\nworld\n")) // => ["hello", "world"]linesWithSeparators
Returns an IterableIterator which yields each line contained within the
string as well as the trailing newline character.
Signature
declare function linesWithSeparators(s: string): LinesIteratorExample
(Iterating lines with separators)
import { String } from "effect"
Array.from(String.linesWithSeparators("hello\nworld\n")) // => ["hello\n", "world\n"]Transforming
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) => stringcamelToSnake
Converts a camelCase string to snake_case.
Signature
declare function camelToSnake(self: string): stringExample
(Converting camelCase to snake_case)
import { String } from "effect"
String.camelToSnake("helloWorld") // => "hello_world"String.camelToSnake("fooBarBaz") // => "foo_bar_baz"capitalize
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
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) => stringconstantCase
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) => stringConverts 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) => stringkebabToSnake
Converts a kebab-case string to snake_case.
Signature
declare function kebabToSnake(self: string): stringExample
(Converting kebab-case to snake_case)
import { String } from "effect"
String.kebabToSnake("hello-world") // => "hello_world"String.kebabToSnake("foo-bar-baz") // => "foo_bar_baz"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;}Normalizes a string according to the specified Unicode normalization form.
Signature
declare function normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD"): (self: string) => stringExample
(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]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) => stringExample
(Padding strings at the end)
import { pipe, String } from "effect"
pipe("a", String.padEnd(5)) // => "a "pipe("a", String.padEnd(5, "_")) // => "a____"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) => stringExample
(Padding strings at the start)
import { pipe, String } from "effect"
pipe("a", String.padStart(5)) // => " a"pipe("a", String.padStart(5, "_")) // => "____a"pascalCase
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) => stringpascalToSnake
Converts a PascalCase string to snake_case.
Signature
declare function pascalToSnake(self: string): stringExample
(Converting PascalCase to snake_case)
import { String } from "effect"
String.pascalToSnake("HelloWorld") // => "hello_world"String.pascalToSnake("FooBarBaz") // => "foo_bar_baz"Repeats the string the specified number of times.
Signature
declare function repeat(count: number): (self: string) => stringExample
(Repeating strings)
import { pipe, String } from "effect"
pipe("a", String.repeat(5)) // => "aaaaa"pipe("hello", String.repeat(3)) // => "hellohellohello"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) => stringExample
(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
Replaces all occurrences of a substring or pattern in a string.
Signature
declare function replaceAll(searchValue: string | RegExp, replaceValue: string): (self: string) => stringExample
(Replacing all matches)
import { pipe, String } from "effect"
pipe("ababb", String.replaceAll("b", "c")) // => "acacc"pipe("ababb", String.replaceAll(/ba/g, "cc")) // => "accbb"Extracts a section of a string and returns it as a new string.
Signature
declare function slice(start?: number, end?: number): (self: string) => stringExample
(Slicing strings)
import { pipe, String } from "effect"
pipe("abcd", String.slice(1, 3)) // => "bc"pipe("hello world", String.slice(0, 5)) // => "hello"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) => stringsnakeToCamel
Converts a snake_case string to camelCase.
Signature
declare function snakeToCamel(self: string): stringExample
(Converting snake_case to camelCase)
import { String } from "effect"
String.snakeToCamel("hello_world") // => "helloWorld"String.snakeToCamel("foo_bar_baz") // => "fooBarBaz"snakeToKebab
Converts a snake_case string to kebab-case.
Signature
declare function snakeToKebab(self: string): stringExample
(Converting snake_case to kebab-case)
import { String } from "effect"
String.snakeToKebab("hello_world") // => "hello-world"String.snakeToKebab("foo_bar_baz") // => "foo-bar-baz"snakeToPascal
Converts a snake_case string to PascalCase.
Signature
declare function snakeToPascal(self: string): stringExample
(Converting snake_case to PascalCase)
import { String } from "effect"
String.snakeToPascal("hello_world") // => "HelloWorld"String.snakeToPascal("foo_bar_baz") // => "FooBarBaz"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
Strips a leading | margin prefix from every line.
Signature
declare function stripMargin(self: string): stringExample
(Stripping pipe margins)
import { String } from "effect"
String.stripMargin(" |hello\n |world") // => "hello\nworld"stripMarginWith
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"Extracts characters from a string between two specified indices.
Signature
declare function substring(start: number, end?: number): (self: string) => stringExample
(Extracting substrings)
import { pipe, String } from "effect"
pipe("abcd", String.substring(1)) // => "bcd"pipe("abcd", String.substring(1, 3)) // => "bc"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"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"toLocaleLowerCase
Converts the string to lowercase according to the specified locale.
Signature
declare function toLocaleLowerCase(locale?: string | Array<string>): (self: string) => stringExample
(Lowercasing strings by locale)
import { pipe, String } from "effect"
const str = "\u0130"pipe(str, String.toLocaleLowerCase("tr")) // => "i"toLocaleUpperCase
Converts the string to uppercase according to the specified locale.
Signature
declare function toLocaleUpperCase(locale?: string | Array<string>): (self: string) => stringExample
(Uppercasing strings by locale)
import { pipe, String } from "effect"
const str = "i\u0307"pipe(str, String.toLocaleUpperCase("lt-LT")) // => "I"toLowerCase
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
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"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"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"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
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"