From 3612bfcbcb1d0fb0168a9717ce70c7a08b1fc860 Mon Sep 17 00:00:00 2001 From: Valentin Agachi Date: Thu, 29 Jul 2021 19:00:33 +0200 Subject: [PATCH] Add `Join` type --- readme.md | 3 ++- test-d/join.ts | 19 +++++++++++++++++++ ts41/index.d.ts | 1 + ts41/join.d.ts | 22 ++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test-d/join.ts create mode 100644 ts41/join.d.ts diff --git a/readme.md b/readme.md index 34b034cc4..68c62212c 100644 --- a/readme.md +++ b/readme.md @@ -140,7 +140,8 @@ Click the type names for complete docs. - [`DelimiterCase`](ts41/delimiter-case.d.ts) – Convert a string literal to a custom string delimiter casing. - [`DelimiterCasedProperties`](ts41/delimiter-cased-properties.d.ts) – Convert object properties to a custom string delimiter casing. - [`DelimiterCasedPropertiesDeep`](ts41/delimiter-cased-properties-deep.d.ts) – Convert object properties to a custom string delimiter casing recursively. -- [`Split`](ts41/split.d.ts) - Represents an array of strings split using a given character or character set. +- [`Join`](ts41/join.d.ts) - Join an array of strings using the given string as delimiter. +- [`Split`](ts41/split.d.ts) - Represents an array of strings split using the given character or character set. - [`Trim`](ts41/trim.d.ts) - Remove leading and trailing spaces from a string. - [`Get`](ts41/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. - [`LastArrayElement`](ts41/last-array-element.d.ts) - Extracts the type of the last element of an array. diff --git a/test-d/join.ts b/test-d/join.ts new file mode 100644 index 000000000..f50e8c77f --- /dev/null +++ b/test-d/join.ts @@ -0,0 +1,19 @@ +import {expectError, expectType} from 'tsd'; +import {Join} from '../ts41'; + +// 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); diff --git a/ts41/index.d.ts b/ts41/index.d.ts index a358f9c54..d910eb82b 100644 --- a/ts41/index.d.ts +++ b/ts41/index.d.ts @@ -18,6 +18,7 @@ export {ScreamingSnakeCase} from './screaming-snake-case'; export {DelimiterCase} from './delimiter-case'; export {DelimiterCasedProperties} from './delimiter-cased-properties'; export {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep'; +export {Join} from './join'; export {Split} from './split'; export {Trim} from './trim'; export {Get} from './get'; diff --git a/ts41/join.d.ts b/ts41/join.d.ts new file mode 100644 index 000000000..3f062913b --- /dev/null +++ b/ts41/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;