string-ts

Strongly typed string functions

README

string-ts


Strongly-typed string functions for all!

A demonstration of string-ts

😬 The problem


When you are working with literal strings, the string manipulation functions only work at the runtime level and the types don't follow those transformations.
You end up losing type information and possibly having to cast the result.

  1. ```ts
  2. const str = 'hello-world'
  3. const result = str.replace('-', ' ') // you should use: as 'hello world'
  4. //    ^? string
  5. ```

🤓 The solution


This library aims to solve this problem by providing a set of common functions that work with literal strings at both type and runtime level.

  1. ```ts
  2. import { replace } from 'string-ts'

  3. const str = 'hello-world'
  4. const result = replace(str, '-', ' ')
  5. //    ^ 'hello world'
  6. ```

🔍 Why this matters


TypeScript yields the best static analysis when types are highly specific.
Literals are more specific than type string.
This library preserves literals (and unions of literals) after transformations, unlike most existing utility libraries (and built-in string methods.)

In-depth example


In the below example, I want to get a strongly-typed, camel-case version of process.env.
One flow results in a loose type, and the other results in a more precise type.
This example should illustrate the highly-specific and flexible nature of string-ts.

  1. ```ts
  2. import { deepCamelKeys } from 'string-ts'
  3. import { camelCase, mapKeys } from 'lodash-es'
  4. import z from 'zod'

  5. const EnvSchema = z.object({
  6.   NODE_ENV: z.string(),
  7. })

  8. function getEnvLoose() {
  9.   const rawEnv = EnvSchema.parse(process.env)
  10.   const env = mapKeys(rawEnv, (_v, k) => camelCase(k))
  11.   //    ^? Dictionary

  12.   // `Dictionary` is too loose
  13.   // TypeScript is okay with this, 'abc' is expected to be of type `string`
  14.   // This will have unexpected behavior at runtime
  15.   console.log(env.abc)
  16. }

  17. function getEnvPrecise() {
  18.   const rawEnv = EnvSchema.parse(process.env)
  19.   const env = deepCamelKeys(rawEnv)
  20.   //    ^? { nodeEnv: string }

  21.   // Error: Property 'abc' does not exist on type '{ nodeEnv: string; }'
  22.   // Our type is more specific, so TypeScript catches this error.
  23.   // This mistake will be caught at compile time
  24.   console.log(env.abc)
  25. }

  26. function main() {
  27.   getEnvLoose()
  28.   getEnvPrecise()
  29. }

  30. main()
  31. ```

📦 Installation


  1. ```bash
  2. npm install string-ts
  3. ```

🌳 Tree shaking


string-ts has been designed with tree shaking in mind.
We have tested it with build tools like Webpack, Vite, Rollup, etc.

👌 Supported TypeScript versions


string-ts currently only works on TypeScript v5+.

It also only work with common ASCII characters characters. We don't plan to support international characters or emojis.


📖 API


  - charAt
  - concat
  - endsWith
  - includes
  - join
  - length
  - padEnd
  - padStart
  - repeat
  - replace
  - slice
  - split
  - trim
  - trimEnd
  - trimStart
  - camelCase
  - kebabCase
  - reverse
  - snakeCase
  - titleCase
  - truncate
  - words
  - camelKeys
  - kebabKeys
  - snakeKeys


Runtime counterparts of native type utilities


capitalize


Capitalizes the first letter of a string. This is a runtime counterpart of `Capitalize` from `src/types.d.ts`.

  1. ```ts
  2. import { capitalize } from 'string-ts'

  3. const str = 'hello world'
  4. const result = capitalize(str)
  5. //    ^ 'Hello world'
  6. ```

uncapitalize


Uncapitalizes the first letter of a string. This is a runtime counterpart of `Uncapitalize` from `src/types.d.ts`.

  1. ```ts
  2. import { uncapitalize } from 'string-ts'

  3. const str = 'Hello world'
  4. const result = uncapitalize(str)
  5. //    ^ 'hello world'
  6. ```

Strongly-typed alternatives to native runtime utilities


charAt


This function is a strongly-typed counterpart of String.prototype.charAt.

  1. ```ts
  2. import { charAt } from 'string-ts'

  3. const str = 'hello world'
  4. const result = charAt(str, 6)
  5. //    ^ 'w'
  6. ```

concat


This function is a strongly-typed counterpart of String.prototype.concat.

  1. ```ts
  2. import { concat } from 'string-ts'

  3. const result = concat('a', 'bc', 'def')
  4. //    ^ 'abcdef'
  5. ```

endsWith


This function is a strongly-typed counterpart of String.prototype.endsWith.

  1. ```ts
  2. import { endsWith } from 'string-ts'

  3. const result = endsWith('abc', 'c')
  4. //    ^ true
  5. ```

includes


This function is a strongly-typed counterpart of String.prototype.includes.

  1. ```ts
  2. import { includes } from 'string-ts'

  3. const result = includes('abcde', 'bcd')
  4. //    ^ true
  5. ```

join


This function is a strongly-typed counterpart of Array.prototype.join.

  1. ```ts
  2. import { join } from 'string-ts'

  3. const str = ['hello', 'world']
  4. const result = join(str, ' ')
  5. //    ^ 'hello world'
  6. ```

length


This function is a strongly-typed counterpart of String.prototype.length.

  1. ```ts
  2. import { length } from 'string-ts'

  3. const str = 'hello'
  4. const result = length(str)
  5. //    ^ 5
  6. ```

padEnd


This function is a strongly-typed counterpart of String.prototype.padEnd.

  1. ```ts
  2. import { padEnd } from 'string-ts'

  3. const str = 'hello'
  4. const result = padEnd(str, 10, '=')
  5. //    ^ 'hello====='
  6. ```

padStart


This function is a strongly-typed counterpart of String.prototype.padStart.

  1. ```ts
  2. import { padStart } from 'string-ts'

  3. const str = 'hello'
  4. const result = padStart(str, 10, '=')
  5. //    ^ '=====hello'
  6. ```

repeat


This function is a strongly-typed counterpart of String.prototype.repeat.

  1. ```ts
  2. import { repeat } from 'string-ts'

  3. const str = 'abc'
  4. const result = repeat(str, 3)
  5. //    ^ 'abcabcabc'
  6. ```

replace


This function is a strongly-typed counterpart of String.prototype.replace.

_Warning: this is a partial implementation, as we don't fully support Regex. Using a RegExp lookup will result in a loose typing._

  1. ```ts
  2. import { replace } from 'string-ts'

  3. const str = 'hello-world-'
  4. const result = replace(str, '-', ' ')
  5. //    ^ 'hello world-'
  6. const looselyTypedResult = replace(str, /-/, ' ')
  7. //    ^ string
  8. ```

replaceAll


This function is a strongly-typed counterpart of String.prototype.replaceAll.
It also has a polyfill for runtimes older than ES2021.

_Warning: this is a partial implementation, as we don't fully support Regex. Using a RegExp lookup will result in a loose typing._

  1. ```ts
  2. import { replaceAll } from 'string-ts'

  3. const str = 'hello-world-'
  4. const result = replaceAll(str, '-', ' ')
  5. //    ^ 'hello world '
  6. const looselyTypedResult = replaceAll(str, /-/g, ' ')
  7. //    ^ string
  8. ```

slice


This function is a strongly-typed counterpart of String.prototype.slice.

  1. ```ts
  2. import { slice } from 'string-ts'

  3. const str = 'hello-world'
  4. const result = slice(str, 6)
  5. //    ^ 'world'
  6. const result2 = slice(str, 1, 5)
  7. //    ^ 'ello'
  8. const result3 = slice(str, -5)
  9. //    ^ 'world'
  10. ```

split


This function is a strongly-typed counterpart of String.prototype.split.

  1. ```ts
  2. import { split } from 'string-ts'

  3. const str = 'hello-world'
  4. const result = split(str, '-')
  5. //    ^ ['hello', 'world']
  6. ```

startsWith


This function is a strongly-typed counterpart of String.prototype.startsWith.

  1. ```ts
  2. import { startsWith } from 'string-ts'

  3. const result = startsWith('abc', 'a')
  4. //    ^ true
  5. ```

toLowerCase


This function is a strongly-typed counterpart of String.prototype.toLowerCase.

  1. ```ts
  2. import { toLowerCase } from 'string-ts'

  3. const str = 'HELLO WORLD'
  4. const result = toLowerCase(str)
  5. //    ^ 'hello world'
  6. ```

toUpperCase


This function is a strongly-typed counterpart of String.prototype.toUpperCase.

  1. ```ts
  2. import { toUpperCase } from 'string-ts'

  3. const str = 'hello world'
  4. const result = toUpperCase(str)
  5. //    ^ 'HELLO WORLD'
  6. ```

trim


This function is a strongly-typed counterpart of String.prototype.trim.

  1. ```ts
  2. import { trim } from 'string-ts'

  3. const str = '  hello world  '
  4. const result = trim(str)
  5. //    ^ 'hello world'
  6. ```