Skip to content

Commit

Permalink
🐛 Improve type inference
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed Jul 2, 2021
1 parent 4dabc80 commit ed088ba
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 80 deletions.
87 changes: 87 additions & 0 deletions common/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
import { slice } from '../deps.ts'

/**
* @example
* ```ts
* InitString<string> // string
* InitString<''> // ''
* InitString<'a'> // ''
* InitString<'ab'> // 'a'
* InitString<'abcd'> // 'abc'
* ```
* @internal
*/
type InitString<T extends string> = T extends `${infer F}${infer R}`
? R extends ''
? ''
: `${F}${InitString<R>}`
: T extends ''
? ''
: string

/**
* Infer the init types.
* @typeParam T - `string` or any `array`
*
* @example
* ```ts
* // String
* Init<string> // string
* Init<''> // ''
* Init<'hello'> // 'hell'
* ```
*
* @example
* ```ts
* // Array
* Init<[] | never[] | readonly [] | readonly never[]> // []
* Init<['hello', 'world']> // 'hello'
* ```
*
* @category `Array` `String`
*
* @see Related to {@link First}
*
* @public
*/
type Init<T extends string | readonly unknown[]> = T extends string
? InitString<T>
: T extends readonly never[] | []
? []
: T extends readonly [...infer I, unknown]
? I
: T

/**
* Returns all but the init element of the given list or string.
* @param val - string or any array object
* @returns The result of `val.slice(0, -1)`
*
* @example
* ```ts
* // String
* init('hello') // 'hell'
* init('h') // ''
* init('') // ''
* ```
*
* @example
* ```ts
* init([1, 2, 3]) // [1, 2]
* init(['hello', 'world']) // ['hello']
* init(['hello']) // []
* init([]) // []
* ```
*
* @category `Array` `String`
*
* @see Related to {@link tail}
*
* @public
*/
const init = <T extends string | readonly unknown[]>(val: T): Init<T> =>
slice(0, -1, val) as Init<T>

export { init }
export type { Init }
14 changes: 12 additions & 2 deletions test/init.test.ts → common/init_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 { init } from '../src/init.ts'
import { assertEquals, assertEqualsType } from '../dev_deps.ts'
import { Init, init } from './init.ts'

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

assertEqualsType<[], Init<[]>>()
assertEqualsType<readonly [], Init<readonly []>>()
assertEqualsType<[], Init<[1]>>()
assertEqualsType<[1], Init<[1, 2]>>()
assertEqualsType<[1, 2], Init<[1, 2, 3]>>()
assertEqualsType<'', Init<''>>()
assertEqualsType<'', Init<'a'>>()
assertEqualsType<'a', Init<'ab'>>()
assertEqualsType<'abcde', Init<'abcdef'>>()
})
2 changes: 2 additions & 0 deletions common/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
export type { Head } from './head.ts'
export { head } from './head.ts'
export type { Init } from './init.ts'
export { init } from './init.ts'
export type { Last } from './last.ts'
export { last } from './last.ts'
3 changes: 2 additions & 1 deletion deps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
export { length } from 'https://deno.land/x/core_fn@v1.0.0-beta.8/mod.ts'
export { length } from 'https://deno.land/x/core_fn@v1.0.0-beta.14/mod.ts'
export { slice } from 'https://deno.land/x/core_fn@v1.0.0-beta.14/uncurry/common/slice.ts'
export { curry } from 'https://deno.land/x/curry@v1.0.0/mod.ts'
export { equal } from 'https://deno.land/x/equal@v1.5.0/mod.ts'
export {
Expand Down
4 changes: 4 additions & 0 deletions dev_deps.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-unused-vars */

export {
assert,
assertEquals
} from 'https://deno.land/std@0.97.0/testing/asserts.ts'
export const assertEqualsType = <T, U extends T = T>(_actual?: U): void => {}
export { length } from 'https://deno.land/x/core_fn@v1.0.0-beta.8/mod.ts'
export {
isNumber,
Expand Down
1 change: 0 additions & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export { identity } from './src/identity.ts'
export { ifElse } from './src/ifElse.ts'
export { ifElseFn } from './src/ifElseFn.ts'
export { inc } from './src/inc.ts'
export { init } from './src/init.ts'
export { K } from './src/K.ts'
export { lt } from './src/lt.ts'
export { lte } from './src/lte.ts'
Expand Down
36 changes: 0 additions & 36 deletions src/init.ts

This file was deleted.

40 changes: 0 additions & 40 deletions test/init.ts

This file was deleted.

0 comments on commit ed088ba

Please sign in to comment.