diff --git a/index.d.ts b/index.d.ts index f7b4b3800..4c81fb06e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -52,6 +52,7 @@ export {ScreamingSnakeCase} from './source/screaming-snake-case'; export {DelimiterCase} from './source/delimiter-case'; export {DelimiterCasedProperties} from './source/delimiter-cased-properties'; export {DelimiterCasedPropertiesDeep} from './source/delimiter-cased-properties-deep'; +export {Join} from './source/join'; export {Split} from './source/split'; export {Trim} from './source/trim'; export {Includes} from './source/includes'; diff --git a/readme.md b/readme.md index f0c29602d..ab54fc76d 100644 --- a/readme.md +++ b/readme.md @@ -143,6 +143,7 @@ Click the type names for complete docs. - [`DelimiterCase`](source/delimiter-case.d.ts) – Convert a string literal to a custom string delimiter casing. - [`DelimiterCasedProperties`](source/delimiter-cased-properties.d.ts) – Convert object properties to a custom string delimiter casing. - [`DelimiterCasedPropertiesDeep`](source/delimiter-cased-properties-deep.d.ts) – Convert object properties to a custom string delimiter casing recursively. +- [`Join`](source/join.d.ts) - Join an array of strings using the given string as delimiter. - [`Split`](source/split.d.ts) - Represents an array of strings split using a given character or character set. - [`Trim`](source/trim.d.ts) - Remove leading and trailing spaces from a string. - [`Get`](source/get.d.ts) - Get a deeply-nested property from an object using a key path, like [Lodash's `.get()`](https://lodash.com/docs/latest#get) function. diff --git a/source/join.d.ts b/source/join.d.ts new file mode 100644 index 000000000..cab0ec0b3 --- /dev/null +++ b/source/join.d.ts @@ -0,0 +1,22 @@ +/** +Join an array of strings using the given string as delimiter. + +Use-case: Defining key paths in a nested object. For example, for dot-notation fields in MongoDB queries. + +@example +``` +import {Join} from 'type-fest'; + +const path: Join<['foo', 'bar', 'baz'], '.'> = ['foo', 'bar', 'baz'].join('.'); +``` + +@category Template Literals +*/ +export type Join< + Strings extends string[], + Delimiter extends string, +> = Strings extends [] ? '' : + Strings extends [string] ? `${Strings[0]}` : + // @ts-expect-error `Rest` is inferred as `unknown` here: https://github.com/microsoft/TypeScript/issues/45281 + Strings extends [string, ...infer Rest] ? `${Strings[0]}${Delimiter}${Join}` : + string; diff --git a/test-d/join.ts b/test-d/join.ts new file mode 100644 index 000000000..5959c2a41 --- /dev/null +++ b/test-d/join.ts @@ -0,0 +1,19 @@ +import {expectError, expectType} from 'tsd'; +import {Join} from '../index'; + +// General use. +const generalTest: Join<['foo', 'bar', 'baz'], '.'> = 'foo.bar.baz'; +expectType<'foo.bar.baz'>(generalTest); +expectError<'foo'>(generalTest); +expectError<'foo.bar'>(generalTest); +expectError<'foo.bar.ham'>(generalTest); + +// Empty string delimiter. +const emptyDelimiter: Join<['foo', 'bar', 'baz'], ''> = 'foobarbaz'; +expectType<'foobarbaz'>(emptyDelimiter); +expectError<'foo.bar.baz'>(emptyDelimiter); + +// Empty input. +const emptyInput: Join<[], '.'> = ''; +expectType<''>(emptyInput); +expectError<'foo'>(emptyInput);