Skip to content

Commit

Permalink
✨ Add map function
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed May 9, 2021
1 parent 4521d91 commit 337a5d8
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export { length } from './src/length.ts'
export { lowerCase } from './src/lowerCase.ts'
export { lt } from './src/lt.ts'
export { lte } from './src/lte.ts'
export { map } from './src/map.ts'
export { multiply } from './src/multiply.ts'
export { not } from './src/not.ts'
export { or } from './src/or.ts'
Expand Down
50 changes: 50 additions & 0 deletions src/_/mapArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.

/**
* Infer `Array.map` types
*
* @typeParam T - Return types of function
* @typeParam U - Input any array
* @returns Mapped array types
*
* @example
* ```ts
* MapArray<void, any[]> // undefined[]
* MapArray<1, any[]> // 1[]
* MapArray<1, []> // []
* ```
*
* @category `Array`
*
* @internal
*/
type MapArray<T, U> = U extends readonly [] | readonly never[]
? []
: T extends void
? undefined[]
: T[]

/**
* Takes a function, applies the function to each, and returns a result of the same shape.
*
* @param fn - The function to be called on every element of the input array.
* @param array - The array to be iterated over
* @returns The result of `array.map(fn)`
*
* @example
* ```ts
* const triple = (val: number):number => val * 3
* mapArray(triple, [1, 2, 3]) // [3, 6, 9]
* ```
*
* @category `Array`
*
* @internal
*/
const mapArray = <T extends readonly unknown[], U>(
fn: (value: T[number], index: number, array: T) => U,
array: T
): MapArray<U, T> => array.map(fn as never) as MapArray<U, T>

export { mapArray }
export type { MapArray }
25 changes: 25 additions & 0 deletions src/map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.

import { MapArray, mapArray as _mapArray } from './_/mapArray.ts'

/**
* Takes a function, applies the function to each, and returns a result of the same shape.
*
* @param fn - The function to be called on every element of the input array.
* @param array - The array to be iterated over.
* @returns The result of `array.map(fn)`
*
* @example
* ```ts
* const triple = (val: number):number => val * 3
* map(triple, [1, 2, 3]) // [3, 6, 9]
* ```
*
* @category `Array`
*
* @beta
*/
const map = _mapArray

export { map }
export type { MapArray }
47 changes: 47 additions & 0 deletions test/_/mapArray.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2021-present the Fonction authors. All rights reserved. MIT license.

/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/ban-types */
import { assertEquals } from '../../deps.ts'
import { MapArray, mapArray } from '../../src/_/mapArray.ts'
import { AnyFn } from '../../src/types/index.ts'
import { assertEqual } from '../asserts.ts'
Deno.test('mapArray', () => {
const table: [AnyFn, unknown[], unknown[]][] = [
[() => {}, [], []],
[() => 1, [], []],
[() => '', [], []],
[() => {}, [''], [undefined]],
[() => {}, ['', 1], [undefined, undefined]],
[() => {}, ['', 1, {}], [undefined, undefined, undefined]],
[() => 1, [[]], [1]],
[() => 1, [[], [], 1, 0], [1, 1, 1, 1]]
]
table.forEach(([fn, array, expected]) => {
assertEquals(
mapArray(fn, array),
expected,
`mapArray(${fn}, ${array}) -> ${expected}`
)
})

assertEqual<[]>(mapArray(() => {}, []))
assertEqual<[]>(mapArray(() => {}, [] as []))
assertEqual<[]>(mapArray(() => {}, [] as const))
assertEqual<[]>(mapArray(() => 1, []))
assertEqual<1[]>(mapArray(() => 1, ['']))
assertEqual<1[]>(mapArray(() => 1, [''] as const))
assertEqual<1[]>(mapArray(() => 1, [''] as ['']))
assertEqual<(1 | 2)[]>(mapArray(() => 1 as 1 | 2, [''] as ['']))
assertEqual<number[]>(mapArray(() => 1, [[]]))
assertEqual<1[]>(mapArray(() => 1, [[]]))
assertEqual<1[]>(mapArray(() => 1, [[]] as const))
})

Deno.test('types', () => {
assertEqual<[], MapArray<void, [] | never[]>>()
assertEqual<readonly [], MapArray<void, readonly [] | readonly never[]>>()
assertEqual<undefined[], MapArray<void, [''] | unknown[]>>()
assertEqual<1[], MapArray<1, [''] | unknown[]>>()
assertEqual<number[], MapArray<number, [''] | [[]]>>()
})

0 comments on commit 337a5d8

Please sign in to comment.