Skip to content

Commit

Permalink
✨ Add types of Tail
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed Jul 2, 2021
1 parent e2ce80a commit f8458f5
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 39 deletions.
2 changes: 2 additions & 0 deletions common/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export type { Init } from './init.ts'
export { init } from './init.ts'
export type { Last } from './last.ts'
export { last } from './last.ts'
export type { Tail } from './tail.ts'
export { tail } from './tail.ts'
72 changes: 72 additions & 0 deletions common/tail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
import { slice } from '../deps.ts'

/**
* Infer the tail types.
* @typeParam T - `string` or any `array`
*
* @example
* ```ts
* // String
* Tail<string> // string
* Tail<''> // ''
* Tail<'hello'> // 'ello'
* ```
*
* @example
* ```ts
* // Array
* Tail<[] | never[] | readonly [] | readonly never[]> // []
* Tail<['hello', 'world']> // 'world'
* ```
*
* @category `Array` `String`
*
* @see Related to {@link Init}
*
* @beta
*/
type Tail<T extends string | readonly unknown[]> = T extends string
? T extends `${string}${infer R}`
? R
: T extends ''
? ''
: string
: T extends readonly never[] | []
? []
: T extends readonly [unknown, ...infer R]
? R
: T
/**
* Returns all but the first element of the given list or string.
*
* @param val - string or any array object
* @returns The result of `val.slice(1, Infinity)`
*
* @example
* ```ts
* // String
* tail('hello') // 'ello'
* tail('h') // ''
* tail('') // ''
* ```
*
* @example
* ```ts
* tail([1, 2, 3]) // [2, 3]
* tail(['hello', 'world']) // ['world']
* tail(['hello']) // []
* tail([]) // []
* ```
*
* @category `Array` `String`
*
* @see Related to {@link head}
*
* @public
*/
const tail = <T extends string | readonly unknown[]>(val: T): Tail<T> =>
slice(1, Infinity, val) as Tail<T>

export { tail }
export type { Tail }
18 changes: 16 additions & 2 deletions test/tail.test.ts → common/tail_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
import { assertEquals } from '../dev_deps.ts'
import { tail } from '../src/tail.ts'
import { assertEquals, assertEqualsType } from '../dev_deps.ts'
import { Tail, tail } from './tail.ts'

Deno.test('tail', () => {
const tableString: [string, string][] = [
Expand Down Expand Up @@ -37,4 +37,18 @@ Deno.test('tail', () => {
tableArray.forEach(([val, expected]) => {
assertEquals(tail(val), expected, `tail(${val}) -> ${expected}`)
})

assertEqualsType<string, Tail<string>>()
assertEqualsType<'', Tail<''>>()
assertEqualsType<'', Tail<'a'>>()
assertEqualsType<'b', Tail<'ab'>>()
assertEqualsType<'bcdef', Tail<'abcdef'>>()
assertEqualsType<[], Tail<[]>>()
assertEqualsType<[], Tail<[1]>>()
assertEqualsType<[], Tail<readonly [1]>>()
assertEqualsType<[2], Tail<[1, 2]>>()
assertEqualsType<[2, 3, 4, 5], Tail<[1, 2, 3, 4, 5]>>()
assertEqualsType<[2, 3, 4, 5], Tail<readonly [1, 2, 3, 4, 5]>>()
assertEqualsType<string[], Tail<string[]>>()
assertEqualsType<readonly string[], Tail<readonly string[]>>()
})
1 change: 0 additions & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export { props } from './src/props.ts'
export { subtract } from './src/subtract.ts'
export { sum } from './src/sum.ts'
export { T } from './src/T.ts'
export { tail } from './src/tail.ts'
export { take } from './src/take.ts'
export { takeLast } from './src/takeLast.ts'
export { tap } from './src/tap.ts'
Expand Down
36 changes: 0 additions & 36 deletions src/tail.ts

This file was deleted.

0 comments on commit f8458f5

Please sign in to comment.