diff --git a/index.d.ts b/index.d.ts index 8937b6937..f5ddf294a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -78,6 +78,7 @@ export {DelimiterCasedPropertiesDeep} from './source/delimiter-cased-properties- export {Join} from './source/join'; export {Split} from './source/split'; export {Trim} from './source/trim'; +export {Replace} from './source/replace'; export {Includes} from './source/includes'; export {Get} from './source/get'; export {LastArrayElement} from './source/last-array-element'; diff --git a/readme.md b/readme.md index 3d9ac2f54..f22746a6f 100644 --- a/readme.md +++ b/readme.md @@ -210,6 +210,7 @@ Click the type names for complete docs. - [`Trim`](source/trim.d.ts) - Remove leading and trailing spaces from a string. - [`Split`](source/split.d.ts) - Represents an array of strings split using a given character or character set. +- [`Replace`](source/replace.d.ts) - Represents a string with some or all matches replaced by a replacement. ### Array diff --git a/source/replace.d.ts b/source/replace.d.ts new file mode 100644 index 000000000..df523a999 --- /dev/null +++ b/source/replace.d.ts @@ -0,0 +1,67 @@ +type ReplaceOptions = { + all?: boolean; +}; + +/** +Represents a string with some or all matches replaced by a replacement. + +Use-case: +- `snake-case-path` to `dotted.path.notation` +- Changing date/time format: `01-08-2042` → `01/08/2042` +- Manipulation of type properties, for example, removal of prefixes + +@example +``` +import {Replace} from 'type-fest'; + +declare function replace< + Input extends string, + Search extends string, + Replacement extends string +>( + input: Input, + search: Search, + replacement: Replacement +): Replace; + +declare function replaceAll< + Input extends string, + Search extends string, + Replacement extends string +>( + input: Input, + search: Search, + replacement: Replacement +): Replace; + +// The return type is the exact string literal, not just `string`. + +replace('hello ?', '?', '🦄'); +//=> 'hello 🦄' + +replace('hello ??', '?', '❓'); +//=> 'hello ❓?' + +replaceAll('10:42:00', ':', '-'); +//=> '10-42-00' + +replaceAll('__userName__', '__', ''); +//=> 'userName' + +replaceAll('My Cool Title', ' ', ''); +//=> 'MyCoolTitle' +``` + +@category String +@category Template literal +*/ +export type Replace< + Input extends string, + Search extends string, + Replacement extends string, + Options extends ReplaceOptions = {}, +> = Input extends `${infer Head}${Search}${infer Tail}` + ? Options['all'] extends true + ? Replace<`${Head}${Replacement}${Tail}`, Search, Replacement, Options> + : `${Head}${Replacement}${Tail}` + : Input; diff --git a/test-d/replace.ts b/test-d/replace.ts new file mode 100644 index 000000000..371d02423 --- /dev/null +++ b/test-d/replace.ts @@ -0,0 +1,28 @@ +import {expectType} from 'tsd'; +import type {Replace} from '../index'; + +declare function replace< + Input extends string, + Search extends string, + Replacement extends string, +>( + input: Input, + search: Search, + replacement: Replacement +): Replace; + +declare function replaceAll< + Input extends string, + Search extends string, + Replacement extends string, +>( + input: Input, + search: Search, + replacement: Replacement +): Replace; + +expectType<'hello 🦄'>(replace('hello ?', '?', '🦄')); +expectType<'hello ❓?'>(replace('hello ??', '?', '❓')); +expectType<'10-42-00'>(replaceAll('10:42:00', ':', '-')); +expectType<'userName'>(replaceAll('__userName__', '__', '')); +expectType<'MyCoolTitle'>(replaceAll('My Cool Title', ' ', ''));