Skip to content

Commit

Permalink
Add LastArrayElement, Split, and Trim types (#159)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Misha Kaletsky <15040698+mmkal@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 21, 2021
1 parent 8bd5d27 commit 2f6aa0b
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions base.d.ts
Expand Up @@ -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';
Expand Down
7 changes: 7 additions & 0 deletions readme.md
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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.
Expand Down
23 changes: 23 additions & 0 deletions 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<V extends any[]>(array: V): LastArrayElement<V>;
const array = ['foo', 2];
typeof lastOf(array);
//=> number
```
*/
export type LastArrayElement<ValueType extends unknown[]> =
ValueType extends [infer ElementType]
? ElementType
: ValueType extends [infer _, ...infer Tail]
? LastArrayElement<Tail>
: never;
9 changes: 9 additions & 0 deletions test-d/last-array-element.ts
@@ -0,0 +1,9 @@
import {expectType} from 'tsd';
import {LastArrayElement} from '../ts41';

declare function lastOf<V extends [any, ...any]>(array: V): LastArrayElement<V>;
const array: ['foo', 2, 'bar'] = ['foo', 2, 'bar'];
const mixedArray: ['bar', 'foo', 2] = ['bar', 'foo', 2];

expectType<'bar'>(lastOf(array));
expectType<2>(lastOf(mixedArray));
12 changes: 12 additions & 0 deletions test-d/split.ts
@@ -0,0 +1,12 @@
import {expectType} from 'tsd';
import {Split} from '../ts41';

declare function split<S extends string, D extends string>(string: S, separator: D): Split<S, D>;

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]);
10 changes: 10 additions & 0 deletions test-d/trim.ts
@@ -0,0 +1,10 @@
import {expectType} from 'tsd';
import {Trim} from '../ts41';

declare function trim<S extends string>(value: S): Trim<S>;

expectType<'foo'>(trim(' foo'));
expectType<'bar'>(trim('bar '));
expectType<'baz'>(trim(' baz '));
expectType<'waldo'>(trim(' waldo '));
expectType<'fr ed'>(trim(' fr ed '));
2 changes: 2 additions & 0 deletions ts41/index.d.ts
Expand Up @@ -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';
22 changes: 22 additions & 0 deletions 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<S extends string, D extends string>(string: S, separator: D): Split<S, D>;
type Item = 'foo' | 'bar' | 'baz' | 'waldo';
const items = 'foo,bar,baz,waldo';
let array: Item[];
array = split(items, ',');
```
*/
export type Split<S extends string, D extends string> =
S extends `${infer T}${D}${infer U}`
? [T, ...Split<U, D>]
: [S];
22 changes: 22 additions & 0 deletions ts41/trim.d.ts
@@ -0,0 +1,22 @@
/**
Remove spaces from the left side.
*/
type TrimLeft<V extends string> = V extends ` ${infer R}` ? TrimLeft<R> : V;

/**
Remove spaces from the right side.
*/
type TrimRight<V extends string> = V extends `${infer R} ` ? TrimRight<R> : V;

/**
Remove leading and trailing spaces from a string.
@example
```
import {Trim} from 'type-fest';
Trim<' foo '>
//=> 'foo'
```
*/
export type Trim<V extends string> = TrimLeft<TrimRight<V>>;

0 comments on commit 2f6aa0b

Please sign in to comment.