Skip to content

Str

String utilities for text manipulation and analysis.

Provides comprehensive string operations including case conversion, splitting, matching, replacement, templating, and character utilities. Features type-safe APIs with strong inference for string literals and patterns.

Import

typescript
import { Str } from '@wollybeard/kit'
typescript
import * as Str from '@wollybeard/kit/str'

Namespaces

Provides tools for generating markdown, TSDoc/JSDoc, and TypeScript code. Includes safe JSDoc generation with escaping, builder API, and structured tag helpers.

  • Text - Multi-line text formatting and layout utilities.

Provides functions specifically for working with multi-line strings treated as text content: - Line operations: Split into lines, join lines, map transformations per line - Indentation: Add/remove indentation, strip common leading whitespace - Alignment: Pad text, span to width, fit to exact width - Block formatting: Format blocks with prefixes, styled borders

Use Text for: Operations that treat strings as multi-line content with visual layout (indentation, padding for tables, line-by-line transformations).

Use root Str for: Primitive string operations (split, join, replace, match, trim) that work on strings as atomic values.

  • Visual - Visual-aware string utilities that handle ANSI escape codes and grapheme clusters.

These functions measure and manipulate strings based on their visual appearance, not raw character count. Useful for terminal output, tables, and formatted text.

Builder

[C] defaultRender

typescript
;((value: string[]) => string)

Default render function for string builders. Joins lines with newline characters.

[I] Builder

typescript
interface Builder {
  /**
   * Add lines to the builder.
   * @param linesInput - Lines to add (null values are filtered out)
   * @returns The builder instance for chaining
   */
  (...linesInput: LinesInput): Builder
  /**
   * Add content using template literal syntax.
   * @param strings - Template string array
   * @param values - Interpolated values
   * @returns The builder instance for chaining
   */
  (strings: TemplateStringsArray, ...values: string[]): Builder
  /**
   * The internal state containing accumulated lines.
   */
  state: State
  /**
   * Render the accumulated lines into a single string.
   * @returns The rendered string
   */
  render: () => string
  /**
   * Alias for render() to support string coercion.
   * @returns The rendered string
   */
  toString(): string
}

String builder interface for constructing multi-line strings. Supports both function call syntax and template literal syntax.

[F] Builder

typescript
(options?: { join?: string; } | undefined): Builder

Returns: A new builder instance

Create a new string builder for constructing multi-line strings.

Examples:

typescript
const 
b
=
Str
.Builder()
b
('Line 1')
b
('Line 2', 'Line 3')
b
`Template line`
console
.
log
(
b
.render()) // "Line 1\nLine 2\nLine 3\nTemplate line"

[T] LinesInput

typescript
type LinesInput = (Line | null)[]

Input type for lines

  • allows null values which are filtered out.

[T] Lines

typescript
type Lines = Line[]

Array of line strings.

[T] Line

typescript
type Line = string

A single line of text.

[I] State

typescript
interface State {
  /**
   * Accumulated lines.
   */
  lines: Lines
}

Internal state of the string builder.

Constants

[C] Empty

typescript
''

Empty string constant.

Examples:

typescript
const 
result
= someCondition ? 'hello' : Empty

Formatting

[F] table

typescript
(input: { data: Record<string, string>; separator?: string | false | undefined; separatorAlignment?: boolean; }): string

Parameters:

  • input - Configuration object

Returns: Formatted table string with aligned columns

Format a key-value object as an aligned table string.

Examples:

typescript
Str
.table({
data
: {
name
: 'John',
age
: '25',
city
: 'NYC' },
}) // Returns: // name → John // age → 25 // city → NYC
Str
.table({
data
: {
foo
: 'bar',
hello
: 'world' },
separator
: ' = ',
separatorAlignment
: false,
}) // Returns: // foo = bar // hello = world

Pattern Matching

[F] pattern

typescript
<matches extends Matches>(pattern: RegExp): Pattern<matches>

Parameters:

  • pattern - The regular expression pattern

Returns: A typed pattern that preserves capture group information

Create a typed pattern from a regular expression. Enables type-safe capture groups when used with match.

Examples:

typescript
const 
p
= pattern<{
groups
: ['name', 'age'] }>(/(?<name>\w+) is (?<age>\d+)/)
const
result
= match('John is 25',
p
)
if (
Option
.isSome(
result
)) {
console
.
log
(
result
.value.groups.name) // 'John' (typed)
console
.
log
(
result
.value.groups.age) // '25' (typed)
}

[F] match

typescript
<matches extends Matches>(string: string, pattern: RegExp | Pattern<matches>): Option<RegExpMatchResult<matches>>

Parameters:

  • string - The string to match against
  • pattern - Regular expression or typed pattern

Returns: Option of match result with typed capture groups, or None if no match

Match a string against a pattern with type-safe results.

Examples:

typescript
const 
result
=
Str
.match('hello world', /hello (\w+)/)
if (
Option
.isSome(
result
)) {
console
.
log
(
result
.value[0]) // 'hello world'
console
.
log
(
result
.value[1]) // 'world'
}

Predicates

[F] isMatch

typescript
(value: string, pattern: PatternInput): boolean

Parameters:

  • value - The string to test
  • pattern - String for exact match or RegExp for pattern match

Returns: True if the value matches the pattern

Check if a string matches a pattern.

Examples:

typescript
Str
.isMatch('hello', 'hello') // true
Str
.isMatch('hello', /^h.*o$/) // true
Str
.isMatch('world', 'hello') // false

[C] isMatchOn

typescript
;((value: string) => (pattern: PatternInput) => boolean)

Curried version of isMatch with value first.

Examples:

typescript
const 
isHello
=
Str
.isMatchOn('hello')
isHello
('hello') // true
isHello
(/^h.*o$/) // true

[C] isMatchWith

typescript
;((pattern: PatternInput) => (value: string) => boolean)

Curried version of isMatch with pattern first.

Examples:

typescript
const 
matchesHello
=
Str
.isMatchWith('hello')
matchesHello
('hello') // true
matchesHello
('world') // false

[F] isntMatch

typescript
(pattern: PatternInput): (value: string) => boolean

Parameters:

  • pattern - String for exact match or RegExp for pattern match

Returns: Function that takes a value and returns true if it doesn't match

Check if a string does not match a pattern.

Examples:

typescript
const 
notHello
=
Str
.isntMatch('hello')
notHello
('world') // true
notHello
('hello') // false

[C] isntMatchOn

typescript
;((pattern: PatternInput) => (value: string) => boolean)

Curried version of isntMatch with value first.

[C] isntMatchWith

typescript
;((value: string) => (pattern: PatternInput) => boolean)

Curried version of isntMatch with pattern first.

[F] isMatchAny

typescript
(value: string, patterns: PatternsInput): boolean

Parameters:

  • value - The string to test
  • patterns - Array of strings or RegExp patterns (or a single pattern)

Returns: True if the value matches any pattern

Check if a string matches any of the provided patterns.

Examples:

typescript
Str
.isMatchAny('hello', ['hello', 'world']) // true
Str
.isMatchAny('hello', [/^h/, /o$/]) // true
Str
.isMatchAny('foo', ['hello', 'world']) // false

[C] isMatchAnyOn

typescript
;((value: string) => (patterns: PatternsInput) => boolean)

Curried version of isMatchAny with value first.

[C] isMatchAnyWith

typescript
;((patterns: PatternsInput) => (value: string) => boolean)

Curried version of isMatchAny with patterns first.

Examples:

typescript
const 
matchesGreeting
=
Str
.isMatchAnyWith(['hello', 'hi', /^hey/])
matchesGreeting
('hello') // true
matchesGreeting
('hey there') // true
matchesGreeting
('goodbye') // false

[F] isNotMatchAny

typescript
(patternOrPatterns: PatternsInput): (value: string) => boolean

Parameters:

  • patternOrPatterns - Array of strings or RegExp patterns (or a single pattern)

Returns: Function that takes a value and returns true if it doesn't match any pattern

Check if a string does not match any of the provided patterns.

Examples:

typescript
const 
notGreeting
=
Str
.isNotMatchAny(['hello', 'hi'])
notGreeting
('goodbye') // true
notGreeting
('hello') // false

[C] isNotMatchAnyOn

typescript
;((patternOrPatterns: PatternsInput) => (value: string) => boolean)

Curried version of isNotMatchAny with value first.

[C] isNotMatchAnyWith

typescript
;((value: string) => (patternOrPatterns: PatternsInput) => boolean)

Curried version of isNotMatchAny with patterns first.

Template

[F] interpolate

typescript
(template: string): (args: TemplateArgs) => string

Parameters:

  • template - Template string containing $variable placeholders

Returns: Function that takes args object and returns interpolated string

Interpolate variables into a template string using $variable syntax.

Examples:

typescript
const 
greeting
=
Str
.interpolate('Hello ${name}, you are ${age} years old')
greeting
({
name
: 'John',
age
: 25 }) // 'Hello John, you are 25 years old'
const
template
=
Str
.interpolate('${greeting} ${name}!')
template
({
greeting
: 'Hi',
name
: 'Alice' }) // 'Hi Alice!'

[C] templateVariablePattern

typescript
RegExp

Regular expression pattern to match template variables in $variable format. Captures the variable name inside the braces.

[T] TemplateArgs

typescript
type TemplateArgs = Record<string, Json.Value>

Arguments object for template interpolation. Maps variable names to their JSON-serializable values.

Text Formatting

[Class] Box

typescript
class {

  // Properties
  paddingHooks: Partial<Record<"mainStart" | "mainEnd" | "crossStart" | "crossEnd", ((ctx: any) => number | ((v: number) => number))[]>>
  marginHooks: Partial<Record<"mainStart" | "mainEnd" | "crossStart" | "crossEnd", ((ctx: any) => number | ((v: number) => number))[]>>
  borderEdgeHooks: Partial<Record<"left" | "right" | "top" | "bottom", ((ctx: any) => string | ((v: string) => string))[]>>
  borderCornerHooks: Partial<Record<"topLeft" | "topRight" | "bottomRight" | "bottomLeft", ((ctx: any) => string | ((v: string) => string))[]>>
  borderEdgeStyles: Partial<Record<"left" | "right" | "top" | "bottom", Style>>
  borderCornerStyles: Partial<Record<"topLeft" | "topRight" | "bottomRight" | "bottomLeft", Style>>
  static String: transformOrFail<typeof Box, typeof String, never>

  // Methods
  toString(): string
  content$(content: string | (string | Box)[]): this
  pad$(padding: PaddingInput): this
  margin$(margin: MarginInput): this
  border$(border: BorderInput): this
  span$(span: SpanInput): this
  spanRange$(spanRange: { readonly main?: { readonly min?: number | undefined; readonly max?: number | undefined; } | undefined; readonly cross?: { readonly min?: number | undefined; readonly max?: number | undefined; } | undefined; }): this
  gap$(gap: GapInput): this
  static content(box: Box, content: string | (string | Box)[]): Box
  static pad(box: Box, padding: PaddingInput): Box
  static margin(box: Box, margin: MarginInput): Box
  static border(box: Box, border: BorderInput): Box
  static span(box: Box, span: SpanInput): Box
  static spanRange(box: Box, spanRange: { readonly main?: { readonly min?: number | undefined; readonly max?: number | undefined; } | undefined; readonly cross?: { readonly min?: number | undefined; readonly max?: number | undefined; } | undefined; }): Box
  static gap(box: Box, gap: GapInput): Box
  static encode(box: Box): string
}

Properties:

  • String - Schema for encoding Box to string representation.

This is a one-way transformation - boxes can be encoded to strings, but cannot be decoded from strings.

Box structure with content and optional styling.

[C] OrientationSchema

typescript
Literal<['vertical', 'horizontal']>

Orientation determines the flow direction of the box.

  • vertical: Content flows top-to-bottom (main axis = vertical)
  • horizontal: Content flows left-to-right (main axis = horizontal)

[T] Orientation

typescript
type Orientation = typeof OrientationSchema.Type

Orientation type.

[C] PaddingSchema

typescript
Struct<
  {
    mainStart: optional<typeof Number>
    mainEnd: optional<typeof Number>
    crossStart: optional<typeof Number>
    crossEnd: optional<typeof Number>
  }
>

Padding configuration using logical properties.

Logical properties adapt to orientation:

  • mainStart/mainEnd: Along the flow direction
  • crossStart/crossEnd: Perpendicular to flow

[T] Padding

typescript
type Padding = typeof PaddingSchema.Type

Padding configuration type.

[U] PaddingInput

typescript
type PaddingInput = AxisHand.Input | WithHooks<Padding, 'padding'>

Padding input accepting AxisHand notation and hook functions.

Supports AxisHand patterns:

  • Single value: 2 → all sides
  • Axis shorthands: [2, 4] → [main, cross]
  • Binary axis: [[1, 2], [3, 4]] → [[mainStart, mainEnd], [crossStart, crossEnd]]
  • Per-axis arrays: [[1, 2], 4] → asymmetric main, symmetric cross
  • Object: { main: [1, 2], cross: 4 }
  • With hooks: { main: { start: (ctx) => 2 } }

[C] MarginSchema

typescript
Struct<
  {
    mainStart: optional<typeof Number>
    mainEnd: optional<typeof Number>
    crossStart: optional<typeof Number>
    crossEnd: optional<typeof Number>
  }
>

Margin configuration using logical properties.

Logical properties adapt to orientation (same as Padding).

[T] Margin

typescript
type Margin = typeof MarginSchema.Type

Margin configuration type.

[U] MarginInput

typescript
type MarginInput = AxisHand.Input | WithHooks<Margin, 'margin'>

Margin input accepting AxisHand notation and hook functions.

Supports AxisHand patterns (same as PaddingInput).

[U] SpanValue

typescript
type SpanValue = number | bigint

Span value type

  • size in characters or percentage of parent.

  • number (1): Absolute size in characters

  • bigint: Percentage of parent span (e.g., 50n = 50%)

[C] SpanSchema

typescript
Struct<
  {
    main: optional<Union<[typeof Number, typeof BigIntFromSelf]>>
    cross: optional<Union<[typeof Number, typeof BigIntFromSelf]>>
  }
>

Span configuration using logical properties.

Defines exact/desired size along each axis:

  • main: Size along flow direction (mainSpan)
  • cross: Size perpendicular to flow (crossSpan)

Percentage values (bigint) are resolved relative to parent's available span.

[T] Span

typescript
type Span = typeof SpanSchema.Type

Span configuration type.

[T] SpanInput

typescript
type SpanInput = AxisHand.Input<SpanValue>

Span input accepting AxisHand notation.

Supports AxisHand patterns with SpanValue (number | bigint):

  • Single value: 80 → main and cross both 80 chars
  • Single percentage: 50n → main and cross both 50% of parent
  • Axis shorthands: [50n, 80] → main 50%, cross 80 chars
  • Binary axis: [[40, 50n], [80, 100]] → different start/end (unusual for span)
  • Object: { main: 50n, cross: 80 }

[C] SpanRangeSchema

typescript
Struct<
  {
    main: optional<
      Struct<{ min: optional<typeof Number>; max: optional<typeof Number> }>
    >
    cross: optional<
      Struct<{ min: optional<typeof Number>; max: optional<typeof Number> }>
    >
  }
>

Span range constraints (min/max) using logical properties.

[T] SpanRange

typescript
type SpanRange = typeof SpanRangeSchema.Type

Span range configuration type.

[C] GapSchema

typescript
Struct<{ main: optional<typeof Number>; cross: optional<typeof Number> }>

Gap configuration using logical properties.

Defines space between array items (container property):

  • Vertical orientation: main=newlines between items, cross=spaces between items
  • Horizontal orientation: main=spaces between items, cross=newlines between items

[T] Gap

typescript
type Gap = typeof GapSchema.Type

Gap configuration type.

[U] GapInput

typescript
type GapInput = number | Gap

Gap input accepting number or object with logical properties.

  • number: Same gap on both axes
  • { main?: number, cross?: number }: Per-axis gaps

[C] BorderStyleSchema

typescript
Literal<['single', 'double', 'rounded', 'bold', 'ascii']>

Border style presets.

[T] BorderStyle

typescript
type BorderStyle = typeof BorderStyleSchema.Type

Border style preset type.

[C] BorderEdgesSchema

typescript
Struct<
  {
    top: optional<typeof String>
    right: optional<typeof String>
    bottom: optional<typeof String>
    left: optional<typeof String>
  }
>

Border edge characters (physical coordinates).

[T] BorderEdges

typescript
type BorderEdges = typeof BorderEdgesSchema.Type

Border edge configuration type.

[C] BorderCornersSchema

typescript
Struct<
  {
    topLeft: optional<typeof String>
    topRight: optional<typeof String>
    bottomRight: optional<typeof String>
    bottomLeft: optional<typeof String>
  }
>

Border corner characters (physical coordinates).

[T] BorderCorners

typescript
type BorderCorners = typeof BorderCornersSchema.Type

Border corner configuration type.

[U] BorderEdgesInput

typescript
type BorderEdgesInput =
  | Clockhand.Value<string | CharStyle>
  | WithHooks<BorderEdges, 'border.edges'>
  | {
    [K in keyof BorderEdges]?:
      | string
      | CharStyle
      | WithHook<
        string | undefined,
        StyleCategoryMap[`border.edges.${K & string}`]
      >
  }

Border edge input supporting Clockhand notation, CharStyle, and hook functions.

Supports Clockhand patterns:

  • Single value: '─' → all edges
  • Single styled: { char: '─', color: { foreground: 'blue' } } → all edges
  • Array: ['─', '│', '─', '│'] → [top, right, bottom, left]
  • Object: { top: '─', left: '│' }
  • Object with CharStyle: { top: { char: '─', color: { foreground: 'red' } } }
  • With hooks: { top: (ctx) => '─' }

[U] BorderCornersInput

typescript
type BorderCornersInput =
  | Clockhand.Value<string | CharStyle>
  | WithHooks<BorderCorners, 'border.corners'>
  | {
    [K in keyof BorderCorners]?:
      | string
      | CharStyle
      | WithHook<
        string | undefined,
        StyleCategoryMap[`border.corners.${K & string}`]
      >
  }

Border corner input supporting Clockhand notation, CharStyle, and hook functions.

Supports Clockhand patterns:

  • Single value: '+' → all corners
  • Single styled: { char: '+', color: { foreground: 'yellow' }, bold: true } → all corners
  • Array: ['┌', '┐', '┘', '└'] → [topLeft, topRight, bottomRight, bottomLeft] (clockwise)
  • Object: { topLeft: '┌', topRight: '┐' }
  • Object with CharStyle: { topLeft: { char: '┌', color: { foreground: 'red' }, bold: true } }
  • With hooks: { topLeft: (ctx) => '┌' }

[T] BorderCharsInput

typescript
type BorderCharsInput = {
  edges?: BorderEdgesInput
  corners?: BorderCornersInput
}

Border character configuration input with nested edges/corners.

[C] BorderSchema

typescript
Struct<
  {
    style: optional<Literal<['single', 'double', 'rounded', 'bold', 'ascii']>>
    edges: optional<
      Struct<
        {
          top: optional<typeof String>
          right: optional<typeof String>
          bottom: optional<typeof String>
          left: optional<typeof String>
        }
      >
    >
    corners: optional<
      Struct<
        {
          topLeft: optional<typeof String>
          topRight: optional<typeof String>
          bottomRight: optional<typeof String>
          bottomLeft: optional<typeof String>
        }
      >
    >
  }
>

Border configuration.

Can specify a preset style, custom edges, custom corners, or a combination. Resolution order: style → edges override → corners override.

[T] Border

typescript
type Border = typeof BorderSchema.Type

Border configuration type.

[T] BorderInput

typescript
type BorderInput = {
  style?: BorderStyle
  edges?: BorderEdgesInput
  corners?: BorderCornersInput
}

Border configuration input with hook support.

Supports:

  • style: Preset border style (provides edges and corners)
  • edges: Edge characters (with Clockhand support)
  • corners: Corner characters (with Clockhand support)

Resolution order: style → edges/corners override

[U] BoxContent

typescript
type BoxContent = string | StyledText | readonly (string | StyledText | Box)[]

Content type for Box

  • can be a string, styled text, or array of these and boxes.

Supports:

  • Plain strings: 'Hello'
  • Styled text: { text: 'Hello', color: { foreground: 'red' }, bold: true }
  • Arrays: ['Header', { text: 'Body', color: { foreground: 'green' } }, Box.make(...)]

Traits

[C] Eq

typescript
Eq<string>

Eq trait implementation for strings.

Provides string equality comparison using strict equality (===). String comparison is case-sensitive and considers all Unicode characters.

Examples:

typescript
import { 
Str
} from '@wollybeard/kit'
Str
.Eq.is('hello', 'hello') // true
Str
.Eq.is('hello', 'Hello') // false (case-sensitive)
Str
.Eq.is('', '') // true (empty strings)

[C] Type

typescript
Type<string>

Type trait implementation for strings.

Provides type guard for checking if a value is a string.

Examples:

typescript
import { 
Str
} from '@wollybeard/kit'
Str
.Type.is('hello') // true
Str
.Type.is(123) // false
Str
.Type.is(null) // false

Transformation

[F] titlizeSlug

typescript
(str: string): string

Parameters:

  • str - The slug string to convert

Returns: The title-cased string

Convert a URL slug to title case. Replaces URL path separators with spaces and converts to title case.

Examples:

typescript
Str
.titlizeSlug('foo/bar/baz') // 'Foo Bar Baz'
Str
.titlizeSlug('the/quick/brown/fox') // 'The Quick Brown Fox'
Str
.titlizeSlug('hello-world') // 'Hello-World' (hyphens are preserved)

[F] ensureEnd

typescript
(string: string, ending: string): string

Parameters:

  • string - The string to check
  • ending - The ending to ensure

Returns: The string with the ending ensured

Ensure a string ends with a specific ending, adding it if not present.

[F] trim

typescript
(value: string): string

Parameters:

  • value - The string to trim

Returns: The trimmed string

DEPRECATED

Use String.trim from Effect instead

Remove whitespace from both ends of a string.

Examples:

typescript
Str
.trim(' hello ') // 'hello'
Str
.trim('\n\thello\n\t') // 'hello'

[F] replaceLeading

typescript
(replacement: string, matcher: string, value: string): string

Parameters:

  • replacement - The string to replace the matcher with
  • matcher - The string to match at the beginning
  • value - The string to operate on

Returns: The string with leading matcher replaced

Replace the leading occurrence of a matcher string with a replacement.

Examples:

typescript
Str
.replaceLeading('$', '//', '// comment') // '$ comment'
Str
.replaceLeading('', 'www.', 'www.example.com') // 'example.com'

[F] replaceLeadingWith

typescript
(replacement: string): (matcher: string) => (value: string) => string

Parameters:

  • replacement - The string to replace the matcher with

Returns: Function that takes matcher, then value

Curried version of replaceLeading with replacement first.

[F] replaceLeadingOn

typescript
(value: string): (replacement: string) => (matcher: string) => string

Parameters:

  • value - The string to operate on

Returns: Function that takes replacement, then matcher

Curried version of replaceLeading with value first.

[C] stripLeading

typescript
;((matcher: string) => (value: string) => string)

Remove the leading occurrence of a matcher string. Alias for replaceLeadingWith('').

Examples:

typescript
const 
removePrefix
=
Str
.stripLeading('//')
removePrefix
('// comment') // ' comment'

[F] replace

typescript
(replacement: string, matcher: PatternsInput, value: string): string

Parameters:

  • replacement - The string to replace matches with
  • matcher - String or RegExp pattern(s) to match
  • value - The string to operate on

Returns: The string with all matches replaced

DEPRECATED

Use String.replace or String.replaceAll from Effect instead

Replace all occurrences of patterns with a replacement string.

Examples:

typescript
Str
.replace('_', ' ', 'hello world') // 'hello_world'
Str
.replace('X', /[aeiou]/g, 'hello') // 'hXllX'
Str
.replace('-', [' ', '_'], 'hello world_test') // 'hello-world-test'

[F] replaceWith

typescript
(replacement: string): (matcher: PatternsInput) => (value: string) => string

Parameters:

  • replacement - The string to replace matches with

Returns: Function that takes matcher, then value

Curried version of replace with replacement first.

[F] replaceOn

typescript
(value: string): (replacement: string) => (matcher: PatternsInput) => string

Parameters:

  • value - The string to operate on

Returns: Function that takes replacement, then matcher

Curried version of replace with value first.

[F] append

typescript
(value1: string, value2: string): string

Parameters:

  • value1 - The base string
  • value2 - The string to append

Returns: The concatenated string

DEPRECATED

Use String.concat from Effect instead

Append a string to another string.

Examples:

typescript
Str
.append('hello', ' world') // 'hello world'
Str
.append('foo', 'bar') // 'foobar'

[C] appendOn

typescript
;((value1: string) => (value2: string) => string)

Curried version of append with value1 first.

[C] appendWith

typescript
;((value2: string) => (value1: string) => string)

Curried version of append with value2 first.

Examples:

typescript
const 
addWorld
=
Str
.appendWith(' world')
addWorld
('hello') // 'hello world'

[F] prepend

typescript
(value1: string, value2: string): string

Parameters:

  • value1 - The string to prepend
  • value2 - The base string

Returns: The concatenated string with value1 first

DEPRECATED

Use String.concat from Effect instead (with arguments swapped)

Prepend a string to another string.

Examples:

typescript
Str
.prepend('hello ', 'world') // 'hello world'
Str
.prepend('pre', 'fix') // 'prefix'

[C] prependOn

typescript
;((value1: string) => (value2: string) => string)

Curried version of prepend with value1 first.

[C] prependWith

typescript
;((value2: string) => (value1: string) => string)

Curried version of prepend with value2 first.

Examples:

typescript
const 
toWorld
=
Str
.prependWith('world')
toWorld
('hello ') // 'hello world'

[F] repeat

typescript
(value: string, count: number): string

Parameters:

  • value - The string to repeat
  • count - The number of times to repeat

Returns: The repeated string

DEPRECATED

Use String.repeat from Effect instead

Repeat a string a specified number of times.

Examples:

typescript
Str
.repeat('a', 3) // 'aaa'
Str
.repeat('hello', 2) // 'hellohello'
Str
.repeat('-', 10) // '----------'

[C] repeatOn

typescript
;((value: string) => (count: number) => string)

Curried version of repeat with value first.

[C] repeatWith

typescript
;((count: number) => (value: string) => string)

Curried version of repeat with count first.

Examples:

typescript
const 
triple
=
Str
.repeatWith(3)
triple
('ha') // 'hahaha'

[F] removeSurrounding

typescript
(str: string, target: string): string

Parameters:

  • str - The string to process
  • target - The character to remove from both ends

Returns: The string with surrounding target characters removed

Remove all occurrences of a target character from the beginning and end of a string.

Examples:

typescript
Str
.removeSurrounding(' hello ', ' ') // 'hello'
Str
.removeSurrounding('***test***', '*') // 'test'
Str
.removeSurrounding('aaa', 'a') // ''

[C] removeSurroundingOn

typescript
;((str: string) => (target: string) => string)

Curried version of removeSurrounding with str first.

[C] removeSurroundingWith

typescript
;((target: string) => (str: string) => string)

Curried version of removeSurrounding with target first.

[F] truncate

typescript
(str: string, maxLength?: number = 80): string

Parameters:

  • str - The string to truncate
  • maxLength - Maximum length of the result (default: 80)

Returns: The truncated string with ellipsis if needed

Truncate a string to a maximum length, adding ellipsis if truncated.

Examples:

typescript
Str
.truncate('hello world', 8) // 'hello...'
Str
.truncate('short', 10) // 'short'
Str
.truncate('very long text that needs truncating') // 'very long text that needs truncating...' (if > 80 chars)

[C] truncateOn

typescript
;((str: string) => (maxLength?: number | undefined) => string)

Curried version of truncate with str first.

[C] truncateWith

typescript
;((maxLength?: number | undefined) => (str: string) => string)

Curried version of truncate with maxLength first.

Examples:

typescript
const 
truncate10
=
Str
.truncateWith(10)
truncate10
('hello world') // 'hello w...'

[C] strip

typescript
;((matcher: PatternsInput) => (value: string) => string)

Remove all occurrences of patterns from a string. Alias for replaceWith('').

Examples:

typescript
const 
removeVowels
=
Str
.strip(/[aeiou]/g)
removeVowels
('hello world') // 'hll wrld'

[C] removeSurroundingSpaceRegular

typescript
;((str: string) => string)

Remove regular spaces from the beginning and end of a string. Pre-configured removeSurroundingWith for regular spaces.

[C] removeSurroundingSpaceNoBreak

typescript
;((str: string) => string)

Remove non-breaking spaces from the beginning and end of a string. Pre-configured removeSurroundingWith for non-breaking spaces.

[F] split

typescript
(value: string, separator: string): string[]

Parameters:

  • value - The string to split
  • separator - The separator to split on

Returns: Array of substrings

DEPRECATED

Use String.split from Effect instead

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

Examples:

typescript
Str
.split('a,b,c', ',') // ['a', 'b', 'c']
Str
.split('hello world', ' ') // ['hello', 'world']
Str
.split('', ',') // []

[C] splitOn

typescript
(value: string) => (separator: string) => string[]

Curried version of split with value first.

[C] splitWith

typescript
(separator: string) => (value: string) => string[]

Curried version of split with separator first.

Examples:

typescript
const 
splitByComma
=
Str
.splitWith(',')
splitByComma
('a,b,c') // ['a', 'b', 'c']

[F] join

typescript
(value: string[], separator: string): string

Parameters:

  • value - Array of strings to join
  • separator - The separator to place between strings

Returns: The joined string

DEPRECATED

Use Array.join from Effect instead

Join an array of strings into a single string with a separator.

Examples:

typescript
Str
.join(['a', 'b', 'c'], ',') // 'a,b,c'
Str
.join(['hello', 'world'], ' ') // 'hello world'
Str
.join([], ',') // ''

[C] joinOn

typescript
;((value: string[]) => (separator: string) => string)

Curried version of join with value first.

[C] joinWith

typescript
;((separator: string) => (value: string[]) => string)

Curried version of join with separator first.

Examples:

typescript
const 
joinWith
Comma
=
Str
.joinWith(',')
joinWithComma
(['a', 'b', 'c']) // 'a,b,c'

[F] merge

typescript
(string1: string, string2: string): string

Parameters:

  • string1 - The first string
  • string2 - The second string

Returns: The concatenated string

DEPRECATED

Use String.concat from Effect instead

Merge two strings together (concatenate).

Examples:

typescript
Str
.merge('hello', ' world') // 'hello world'
Str
.merge('foo', 'bar') // 'foobar'

[C] mergeOn

typescript
;((string1: string) => (string2: string) => string)

Curried version of merge with string1 first.

Examples:

typescript
const 
mergeWithHello
=
Str
.mergeOn('hello')
mergeWithHello
(' world') // 'hello world'

Type Guards

[F] isEmpty

typescript
(value: string): boolean

Parameters:

  • value - The string to check

Returns: True if the string is empty

DEPRECATED

Use String.isEmpty from Effect instead

Type guard to check if a string is empty.

Examples:

typescript
Str
.isEmpty('') // true
Str
.isEmpty('hello') // false
Str
.isEmpty(' ') // false

Type Utilities

[T] Empty

typescript
type Empty = ''

Type for an empty string.

Type-Level Utilities

[T] EndsWith

typescript
type EndsWith<S extends string, T extends string> = S extends `${string}${T}`
  ? true
  : false

Check if a string ends with a specific suffix.

[T] StartsWith

typescript
type StartsWith<S extends string, T extends string> = S extends `${T}${string}`
  ? true
  : false

Check if a string starts with a specific prefix.

[T] LastSegment

typescript
type LastSegment<S extends string> = S extends `${string}/${infer Rest}`
  ? LastSegment<Rest>
  : S

Extract the last segment from a path-like string (after the last '/').

[T] RemoveTrailingSlash

typescript
type RemoveTrailingSlash<S extends string> = S extends `${infer Rest}/`
  ? Rest extends '' ? '/' : Rest
  : S

Remove trailing slash from a string.

[T] Split

typescript
type Split<S extends string, D extends string, Acc extends string[] = []> =
  S extends '' ? Acc
    : S extends `${infer Segment}${D}${infer Rest}`
      ? Segment extends '' ? Split<Rest, D, Acc>
      : Segment extends '.' ? Split<Rest, D, Acc>
      : Split<Rest, D, [...Acc, Segment]>
    : S extends '.' ? Acc
    : [...Acc, S]

Split a string by a delimiter, filtering out empty segments and '.' segments. This is useful for path-like strings.

[T] Contains

typescript
type Contains<S extends string, C extends string> = S extends
  `${string}${C}${string}` ? true : false

Check if string contains a character.

Type-Level Utilities $S - The string to measure $Acc - Accumulator tuple for counting (internal)

[T] Length

typescript
type Length<$S extends string, $Acc extends 0[] = []> = $S extends
  `${string}${infer __rest__}` ? Length<__rest__, [...$Acc, 0]>
  : $Acc['length']

Get the length of a string type using tuple counting.

Uses recursive template literal parsing with tuple accumulation to count characters. Limited by TypeScript's recursion depth (typically ~50 levels).

Examples:

typescript
type 
L1
=
Str
.
Length
<'hello'> // 5
type
L2
=
Str
.
Length
<''> // 0
type
L3
=
Str
.
Length
<'a'> // 1

Type-Level Utilities $S - The string to pad $TargetLen - The desired final length $Fill - The character to use for padding (default: '_') $Acc - Accumulator for recursion depth tracking (internal)

[T] PadEnd

typescript
type PadEnd<
  $S extends string,
  $TargetLen extends number,
  $Fill extends string = '_',
  $Acc extends 0[] = [],
> = Length<$S> extends $TargetLen ? $S
  : $Acc['length'] extends 50 // Recursion limit safety
    ? $S
  : PadEnd<`${$S}${$Fill}`, $TargetLen, $Fill, [...$Acc, 0]>

Pad a string to a target length by appending a fill character.

If the string is already at or exceeds the target length, returns it unchanged. Limited by TypeScript's recursion depth (~50 iterations).

Examples:

typescript
type 
P1
=
Str
.
PadEnd
<'foo', 10, '_'> // 'foo_______'
type
P2
=
Str
.
PadEnd
<'hello', 3, '_'> // 'hello' (already longer)
type
P3
=
Str
.
PadEnd
<'abc', 5, '0'> // 'abc00'

Type-Level Utilities $S - The string to pad $TargetLen - The desired final length $Fill - The character to use for padding (default: '0') $Acc - Accumulator for recursion depth tracking (internal)

[T] PadStart

typescript
type PadStart<
  $S extends string,
  $TargetLen extends number,
  $Fill extends string = '0',
  $Acc extends 0[] = [],
> = Length<$S> extends $TargetLen ? $S
  : $Acc['length'] extends 50 // Recursion limit safety
    ? $S
  : PadStart<`${$Fill}${$S}`, $TargetLen, $Fill, [...$Acc, 0]>

Pad a string to a target length by prepending a fill character.

If the string is already at or exceeds the target length, returns it unchanged. Limited by TypeScript's recursion depth (~50 iterations).

Examples:

typescript
type 
P1
=
Str
.
PadStart
<'42', 5, '0'> // '00042'
type
P2
=
Str
.
PadStart
<'hello', 3, '0'> // 'hello' (already longer)
type
P3
=
Str
.
PadStart
<'x', 3, ' '> // ' x'

Type-Level Utilities T - The string type to check $ErrorMessage - Custom error message to display when T is not a literal

[T] LiteralOnly

typescript
type LiteralOnly<
  T extends string,
  $ErrorMessage extends string = 'Expected a literal string',
> = string extends T ? Ts.StaticError<
    $ErrorMessage,
    { ReceivedType: T },
    'Use a string literal instead of string type'
  >
  : T

Constraint that only accepts literal strings. Returns StaticError for non-literal string type with customizable error message.

Other

[C] Arb

typescript
Arb<string>

[I] Box

typescript
interface Box {
  readonly content: BoxContent
}

[∩] RegExpMatchResult

typescript
type RegExpMatchResult<$Matches extends Matches> =
  & Omit<RegExpMatchArray, 'groups'>
  & {
    groups: $Matches['groups'] extends
      readonly [MatchItem, ...readonly MatchItem[]]
      ? ArrMut.ReduceWithIntersection<ToGroupsProperties<$Matches['groups']>>
      : undefined
  }
  & (
    $Matches extends { indicies: readonly [MatchItem, ...readonly MatchItem[]] }
      ? [originalValue: string, ...$Matches['indicies']]
      : [originalValue: string]
  )

[T] Matches

typescript
type Matches = {
  groups?: (string | undefined)[]
  indicies?: (string | undefined)[]
}

[U] PatternInput

typescript
type PatternInput = string | RegExp

[T] PatternsInput

typescript
type PatternsInput = ArrMut.Maybe<string | RegExp>