Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

string-ts

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

string-ts

Strongly-typed string functions.

  • 1.0.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
148K
increased by15.19%
Maintainers
1
Weekly downloads
 
Created
Source

Strongly-typed string functions for all!

😬 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.

const str = 'hello-world'
const result = str.replace('-', ' ') // you should use: as 'hello world'
//    ^? string

🤓 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.

import { replace } from 'string-ts'

const str = 'hello-world'
const result = replace(str, '-', ' ')
//    ^ 'hello world'

🔍 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. Note: All types in this example could be inferred, but are included for demonstrative purposes.

import { deepCamelKeys } from 'string-ts'
import { camelCase, mapKeys } from 'lodash-es'
import type { Dictionary } from 'lodash'
import z from 'zod'

export const EnvSchema = z.object({
  NODE_ENV: z.string(),
})

function getEnvLoose() {
  const rawEnv: { NODE_ENV: string } = EnvSchema.parse(process.env)
  const env: Dictionary<string> = mapKeys(rawEnv, (_v, k) => camelCase(k))

  // `Dictionary<string>` is too loose
  // TypeScript is okay with this, 'abc' will be of type `string`
  console.log(env.abc)
}

function getEnvPrecise() {
  const rawEnv: { NODE_ENV: string } = EnvSchema.parse(process.env)
  const env: { nodeEnv: string } = deepCamelKeys(rawEnv)

  // Error: Property 'abc' does not exist on type '{ nodeEnv: string; }'
  // Our type is more specific, so TypeScript catches this error.
  console.log(env.abc)
}

function main() {
  getEnvLoose()
  getEnvPrecise()
}

main()

📦 Installation

npm install string-ts

📖 API


Runtime counterparts of native type utilities

capitalize

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

import { capitalize } from 'string-ts'

const str = 'hello world'
const result = capitalize(str)
//    ^ 'Hello world'

Strongly-typed alternatives to native runtime utilities

toUpperCase

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

import { toUpperCase } from 'string-ts'

const str = 'hello world'
const result = toUpperCase(str)
//    ^ 'HELLO WORLD'

toLowerCase

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

import { toLowerCase } from 'string-ts'

const str = 'HELLO WORLD'
const result = toLowerCase(str)
//    ^ 'hello world'

trim

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

import { trim } from 'string-ts'

const str = '  hello world  '
const result = trim(str)
//    ^ 'hello world'

trimStart

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

import { trimStart } from 'string-ts'

const str = '  hello world  '
const result = trimStart(str)
//    ^ 'hello world  '

trimEnd

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

import { trimEnd } from 'string-ts'

const str = '  hello world  '
const result = trimEnd(str)
//    ^ '  hello world'

charAt

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

import { charAt } from 'string-ts'

const str = 'hello world'
const result = charAt(str, 6)
//    ^ 'w'

join

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

import { join } from 'string-ts'

const str = ['hello', 'world'] as const
const result = join(str, ' ')
//    ^ 'hello world'

replace

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

import { replace } from 'string-ts'

const str = 'hello-world-'
const result = replace(str, '-', ' ')
//    ^ 'hello world-'

replaceAll

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

import { replaceAll } from 'string-ts'

const str = 'hello-world-'
const result = replaceAll(str, '-', ' ')
//    ^ 'hello world '

split

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

import { split } from 'string-ts'

const str = 'hello-world'
const result = split(str, '-')
//    ^ ['hello', 'world']

Strongly-typed alternatives to common loosely-typed functions

words

This function identifies the words in a string and returns a tuple of words split by separators, differences in casing, numbers, and etc.

import { words } from 'string-ts'

const str = '-20someVery-weird String'
const result = words(str)
//    ^ ['20', 'some', 'Very', 'weird', 'String']

toDelimiterCase

This function converts a string to a new case with a custom delimiter at both runtime and type levels.

import { toDelimiterCase } from 'string-ts'

const str = 'helloWorld'
const result = toDelimiterCase(str, '.')
//    ^ 'hello.World'

toCamelCase

This function converts a string to camelCase at both runtime and type levels.

import { toCamelCase } from 'string-ts'

const str = 'hello-world'
const result = toCamelCase(str)
//    ^ 'helloWorld'

toPascalCase

This function converts a string to PascalCase at both runtime and type levels.

import { toPascalCase } from 'string-ts'

const str = 'hello-world'
const result = toPascalCase(str)
//    ^ 'HelloWorld'

toKebabCase

This function converts a string to kebab-case at both runtime and type levels.

import { toKebabCase } from 'string-ts'

const str = 'helloWorld'
const result = toKebabCase(str)
//    ^ 'hello-world'

toSnakeCase

This function converts a string to snake_case at both runtime and type levels.

import { toSnakeCase } from 'string-ts'

const str = 'helloWorld'
const result = toSnakeCase(str)
//    ^ 'hello_world'

toConstantCase

This function converts a string to CONSTANT_CASE at both runtime and type levels.

import { toConstantCase } from 'string-ts'

const str = 'helloWorld'
const result = toConstantCase(str)
//    ^ 'HELLO_WORLD'

toTitleCase

This function converts a string to Title Case at both runtime and type levels.

import { toTitleCase } from 'string-ts'

const str = 'helloWorld'
const result = toTitleCase(str)
//    ^ 'Hello World'

Strongly-typed shallow transformation of objects

delimiterKeys

This function shallowly converts the keys of an object to a new case with a custom delimiter at both runtime and type levels.

import { delimiterKeys } from 'string-ts';

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const;
const result = delimiterKeys(data, '.');
//    ^ { 'hello.world': { 'foo-bar': 'baz' } }

camelKeys

This function shallowly converts the keys of an object to camelCase at both runtime and type levels.

import { camelKeys } from 'string-ts';

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const;
const result = camelKeys(data);
//    ^ { helloWorld: { 'foo-bar': 'baz' } }

pascalKeys

This function shallowly converts the keys of an object to PascalCase at both runtime and type levels.

import { pascalKeys } from 'string-ts';

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const;
const result = pascalKeys(data);
//    ^ { HelloWorld: { FooBar: 'baz' } }

kebabKeys

This function shallowly converts the keys of an object to kebab-case at both runtime and type levels.

import { kebabKeys } from 'string-ts';

const data = {
  'helloWorld': {
    'fooBar': 'baz',
  },
} as const;
const result = kebabKeys(data);
//    ^ { 'hello-world': { fooBar: 'baz' } }

snakeKeys

This function shallowly converts the keys of an object to snake_case at both runtime and type levels.

import { snakeKeys } from 'string-ts';

const data = {
  'helloWorld': {
    'fooBar': 'baz',
  },
} as const;
const result = snakeKeys(data);
//    ^ { 'hello_world': { 'fooBar': 'baz' } }

constantKeys

This function shallowly converts the keys of an object to CONSTANT_CASE at both runtime and type levels.

import { constantKeys } from 'string-ts';

const data = {
  'helloWorld': {
    'fooBar': 'baz',
  },
} as const;
const result = constantKeys(data);
//    ^ { 'HELLO_WORLD': { 'fooBar': 'baz' } }

Strongly-typed deep transformation of objects

deepDelimiterKeys

This function recursively converts the keys of an object to a new case with a custom delimiter at both runtime and type levels.

import { deepDelimiterKeys } from 'string-ts'

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const
const result = deepDelimiterKeys(data, '.')
//    ^ { 'hello.world': { 'foo.bar': 'baz' } }

deepCamelKeys

This function recursively converts the keys of an object to camelCase at both runtime and type levels.

import { deepCamelKeys } from 'string-ts'

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const
const result = deepCamelKeys(data)
//    ^ { helloWorld: { fooBar: 'baz' } }

deepPascalKeys

This function recursively converts the keys of an object to PascalCase at both runtime and type levels.

import { deepPascalKeys } from 'string-ts'

const data = {
  'hello-world': {
    'foo-bar': 'baz',
  },
} as const
const result = deepPascalKeys(data)
//    ^ { HelloWorld: { FooBar: 'baz' } }

deepKebabKeys

This function recursively converts the keys of an object to kebab-case at both runtime and type levels.

import { deepKebabKeys } from 'string-ts'

const data = {
  helloWorld: {
    fooBar: 'baz',
  },
} as const
const result = deepKebabKeys(data)
//    ^ { 'hello-world': { 'foo-bar': 'baz' } }

deepSnakeKeys

This function recursively converts the keys of an object to snake_case at both runtime and type levels.

import { deepSnakeKeys } from 'string-ts'

const data = {
  helloWorld: {
    fooBar: 'baz',
  },
} as const
const result = deepSnakeKeys(data)
//    ^ { 'hello_world': { 'foo_bar': 'baz' } }

deepConstantKeys

This function recursively converts the keys of an object to CONSTANT_CASE at both runtime and type levels.

import { deepConstantKeys } from 'string-ts'

const data = {
  helloWorld: {
    fooBar: 'baz',
  },
} as const
const result = deepConstantKeys(data)
//    ^ { 'HELLO_WORLD': { 'FOO_BAR': 'baz' } }

Type Utilities

All the functions presented in this API have associated type counterparts.

import type * as St from 'string-ts'

Native TS type utilities

Capitalize<'hello world'> // 'Hello world'
Lowercase<'HELLO WORLD'> // 'hello world'
Uppercase<'hello world'> // 'HELLO WORLD'

General Type utilities from this library

St.Words<'hello-world'> // ['hello', 'world']
St.CharAt<'hello world', 6> // 'w'
St.Join<['hello', 'world'], '-'> // 'hello-world'
St.Replace<'hello-world', 'l', '1'> // 'he1lo-world'
St.ReplaceAll<'hello-world', 'l', '1'> // 'he11o-wor1d'
St.Split<'hello-world', '-'> // ['hello', 'world']
St.TrimStart<' hello world '> // 'hello world '
St.TrimEnd<' hello world '> // ' hello world'
St.Trim<' hello world '> // 'hello world'

Casing type utilities

St.CamelCase<'hello-world'> // 'helloWorld'
St.PascalCase<'hello-world'> // 'HelloWorld'
St.KebabCase<'helloWorld'> // 'hello-world'
St.SnakeCase<'helloWorld'> // 'hello_world'
St.ConstantCase<'helloWorld'> // 'HELLO_WORLD'
St.TitleCase<'helloWorld'> // 'Hello World'
St.DelimiterCase<'hello world', '.'> // 'hello.world'

St.DeepDelimiterKeys<
  {
    'hello-world': { 'foo-bar': 'baz' }
  },
  '.'
> // { 'hello.world': { 'foo.bar': 'baz' } }
St.DeepCamelKeys<{
  'hello-world': { 'foo-bar': 'baz' }
}> // { helloWorld: { fooBar: 'baz' } }
St.DeepPascalKeys<{
  'hello-world': { 'foo-bar': 'baz' }
}> // { HelloWorld: { FooBar: 'baz' } }
St.DeepKebabKeys<{
  helloWorld: { fooBar: 'baz' }
}> // { 'hello-world': { 'foo-bar': 'baz' } }
St.DeepSnakeKeys<{
  helloWorld: { fooBar: 'baz' }
}> // { 'hello_world': { 'foo_bar': 'baz' } }
St.DeepConstantKeys<{
  helloWorld: { fooBar: 'baz' }
}> // { 'HELLO_WORLD': { 'FOO_BAR': 'baz' } }

Other exported type utilities

St.IsDigit<'a'> // false
St.IsDigit<'1'> // true
St.IsLetter<'a'> // true
St.IsLetter<'1'> // false
St.IsLower<'a'> // true
St.IsLower<'A'> // false
St.IsUpper<'a'> // false
St.IsUpper<'A'> // true
St.IsSeparator<' '> // true
St.IsSeparator<'-'> // true
St.IsSeparator<'a'> // false
St.IsSpecial<'a'> // false
St.IsSpecial<'!'> // true
St.IsSpecial<' '> // false

Runtime-only utilities

deepTransformKeys

This function recursively converts the keys of an object to a custom format, but only at runtime level.

import { deepTransformKeys, toUpperCase } from 'string-ts'

const data = { helloWorld: 'baz' } as const

type MyType<T> = { [K in keyof T as Uppercase<K>]: T[K] }
const result = deepTransformKeys(data, toUpperCase) as MyType<typeof data>
//    ^ { 'HELLOWORLD': 'baz' }

Disclaimer

This library doesn't support every internal character for the sake of keeping the maintainer's sanity.

FAQs

Package last updated on 03 Oct 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc