From 2f6aa0b2f78522f7b003021d156d36d06cbf4fd0 Mon Sep 17 00:00:00 2001 From: Kai Niedziela Date: Sun, 21 Mar 2021 13:45:45 +0100 Subject: [PATCH] Add `LastArrayElement`, `Split`, and `Trim` types (#159) Co-authored-by: Sindre Sorhus Co-authored-by: Misha Kaletsky <15040698+mmkal@users.noreply.github.com> --- base.d.ts | 1 + readme.md | 7 +++++++ source/last-array-element.d.ts | 23 +++++++++++++++++++++++ test-d/last-array-element.ts | 9 +++++++++ test-d/split.ts | 12 ++++++++++++ test-d/trim.ts | 10 ++++++++++ ts41/index.d.ts | 2 ++ ts41/split.d.ts | 22 ++++++++++++++++++++++ ts41/trim.d.ts | 22 ++++++++++++++++++++++ 9 files changed, 108 insertions(+) create mode 100644 source/last-array-element.d.ts create mode 100644 test-d/last-array-element.ts create mode 100644 test-d/split.ts create mode 100644 test-d/trim.ts create mode 100644 ts41/split.d.ts create mode 100644 ts41/trim.d.ts diff --git a/base.d.ts b/base.d.ts index 625a05d58..c61ec473d 100644 --- a/base.d.ts +++ b/base.d.ts @@ -33,6 +33,7 @@ export {Entry} from './source/entry'; export {Entries} from './source/entries'; export {SetReturnType} from './source/set-return-type'; export {Asyncify} from './source/asyncify'; +export {LastArrayElement} from './source/last-array-element'; // Miscellaneous export {PackageJson} from './source/package-json'; diff --git a/readme.md b/readme.md index 4fae2d385..f9b603fc3 100644 --- a/readme.md +++ b/readme.md @@ -104,6 +104,7 @@ Click the type names for complete docs. - [`Entries`](source/entries.d.ts) - Create a type that represents the type of the entries of a collection. - [`SetReturnType`](source/set-return-type.d.ts) - Create a function type with a return type of your choice and the same parameters as the given function type. - [`Asyncify`](source/asyncify.d.ts) - Create an async version of the given function type. +- [`LastArrayElement`](source/last-array-element.d.ts) - Extracts the type of the last element of an array. ### Template literal types @@ -114,6 +115,8 @@ Click the type names for complete docs. - [`PascalCase`](ts41/pascal-case.d.ts) – Converts a string literal to pascal-case (`FooBar`) - [`SnakeCase`](ts41/snake-case.d.ts) – Convert a string literal to snake-case (`foo_bar`). - [`DelimiterCase`](ts41/delimiter-case.d.ts) – Convert a string literal to a custom string delimiter casing. +- [`Split`](ts41/split.d.ts) - Represents an array of strings split using a 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. ### Miscellaneous @@ -132,6 +135,10 @@ Click the type names for complete docs. ## Tips +### Related + +- [typed-query-selector](https://github.com/g-plane/typed-query-selector) - Enhances `document.querySelector` and `document.querySelectorAll` with a template literal type that matches element types returned from an HTML element query selector. + ### Built-in types There are many advanced types most users don't know about. diff --git a/source/last-array-element.d.ts b/source/last-array-element.d.ts new file mode 100644 index 000000000..01de4de36 --- /dev/null +++ b/source/last-array-element.d.ts @@ -0,0 +1,23 @@ +/** +Extracts the type of the last element of an array. + +Use-case: Defining the return type of functions that extract the last element of an array, for example [`lodash.last`](https://lodash.com/docs/4.17.15#last). + +@example +``` +import {LastArrayElement} from 'type-fest'; + +declare function lastOf(array: V): LastArrayElement; + +const array = ['foo', 2]; + +typeof lastOf(array); +//=> number +``` +*/ +export type LastArrayElement = + ValueType extends [infer ElementType] + ? ElementType + : ValueType extends [infer _, ...infer Tail] + ? LastArrayElement + : never; diff --git a/test-d/last-array-element.ts b/test-d/last-array-element.ts new file mode 100644 index 000000000..05a2bbb25 --- /dev/null +++ b/test-d/last-array-element.ts @@ -0,0 +1,9 @@ +import {expectType} from 'tsd'; +import {LastArrayElement} from '../ts41'; + +declare function lastOf(array: V): LastArrayElement; +const array: ['foo', 2, 'bar'] = ['foo', 2, 'bar']; +const mixedArray: ['bar', 'foo', 2] = ['bar', 'foo', 2]; + +expectType<'bar'>(lastOf(array)); +expectType<2>(lastOf(mixedArray)); diff --git a/test-d/split.ts b/test-d/split.ts new file mode 100644 index 000000000..a98407504 --- /dev/null +++ b/test-d/split.ts @@ -0,0 +1,12 @@ +import {expectType} from 'tsd'; +import {Split} from '../ts41'; + +declare function split(string: S, separator: D): Split; + +const items = 'foo,bar,baz,waldo'; +const array = split(items, ','); + +expectType<'foo'>(array[0]); +expectType<'bar'>(array[1]); +expectType<'baz'>(array[2]); +expectType<'waldo'>(array[3]); diff --git a/test-d/trim.ts b/test-d/trim.ts new file mode 100644 index 000000000..05b1a0c91 --- /dev/null +++ b/test-d/trim.ts @@ -0,0 +1,10 @@ +import {expectType} from 'tsd'; +import {Trim} from '../ts41'; + +declare function trim(value: S): Trim; + +expectType<'foo'>(trim(' foo')); +expectType<'bar'>(trim('bar ')); +expectType<'baz'>(trim(' baz ')); +expectType<'waldo'>(trim(' waldo ')); +expectType<'fr ed'>(trim(' fr ed ')); diff --git a/ts41/index.d.ts b/ts41/index.d.ts index e49504c15..bff2c62c9 100644 --- a/ts41/index.d.ts +++ b/ts41/index.d.ts @@ -7,4 +7,6 @@ export {KebabCase} from './kebab-case'; export {PascalCase} from './pascal-case'; export {SnakeCase} from './snake-case'; export {DelimiterCase} from './delimiter-case'; +export {Split} from './split'; +export {Trim} from './trim'; export {Get} from './get'; diff --git a/ts41/split.d.ts b/ts41/split.d.ts new file mode 100644 index 000000000..36e541a23 --- /dev/null +++ b/ts41/split.d.ts @@ -0,0 +1,22 @@ +/** +Represents an array of strings split using a given character or character set. + +Use-case: Defining the return type of a method like `String.prototype.split`. + +@example +``` +import {Split} from 'type-fest'; + +declare function split(string: S, separator: D): Split; + +type Item = 'foo' | 'bar' | 'baz' | 'waldo'; +const items = 'foo,bar,baz,waldo'; +let array: Item[]; + +array = split(items, ','); +``` +*/ +export type Split = + S extends `${infer T}${D}${infer U}` + ? [T, ...Split] + : [S]; diff --git a/ts41/trim.d.ts b/ts41/trim.d.ts new file mode 100644 index 000000000..d1c33cdcc --- /dev/null +++ b/ts41/trim.d.ts @@ -0,0 +1,22 @@ +/** +Remove spaces from the left side. +*/ +type TrimLeft = V extends ` ${infer R}` ? TrimLeft : V; + +/** +Remove spaces from the right side. +*/ +type TrimRight = V extends `${infer R} ` ? TrimRight : V; + +/** +Remove leading and trailing spaces from a string. + +@example +``` +import {Trim} from 'type-fest'; + +Trim<' foo '> +//=> 'foo' +``` +*/ +export type Trim = TrimLeft>;