Skip to content

Commit

Permalink
✨ Add flattenDeep function
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed May 4, 2021
1 parent d2c6087 commit 7dadd6b
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 0 deletions.
67 changes: 67 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,34 @@ first(['one', 2, 3, 4]) // 'one'
```
### flattenDeep
<span class="tag beta">beta</span>
Recursively flattens array.
::: warning
This API is provided as a preview for developers and may change based on feedback that we receive.
Do not use this API in a production environment.
:::
**Signature:**
```ts
flattenDeep: <T extends readonly unknown[]>(val: T) => FlattenDeep<T>
```
#### Example
```ts
flattenDeep([]) // []
flattenDeep([1, [2, [3, [4]], 5]]) // [1, 2, 3, 4, 5]
```
### gt
Expand Down Expand Up @@ -1899,6 +1927,45 @@ First<string | number[]> // string | number
```
### FlattenDeep
<span class="tag beta">beta</span>
Infer deep flatted array.
::: warning
This API is provided as a preview for developers and may change based on feedback that we receive.
Do not use this API in a production environment.
:::
**Signature:**
```ts
type FlattenDeep<T extends readonly unknown[]> = T extends readonly [
infer A,
...infer Rest
] ? A extends readonly unknown[] ? [
...FlattenDeep<A>,
...FlattenDeep<Rest>
] : [
A,
...FlattenDeep<Rest>
] : [
...T
];
```
#### Example
```ts
FlattenDeep<[]> // []
FlattenDeep<[[1, [2, [3, [4]], 5]]> // [1, 2, 3, 4, 5]
```
### Last
Expand Down
2 changes: 2 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export { endsWith } from './src/endsWith.ts'
export { F } from './src/F.ts'
export type { First } from './src/first.ts'
export { first } from './src/first.ts'
export type { FlattenDeep } from './src/flattenDeep.ts'
export { flattenDeep } from './src/flattenDeep.ts'
export { gt } from './src/gt.ts'
export { gte } from './src/gte.ts'
export { has } from './src/has.ts'
Expand Down
41 changes: 41 additions & 0 deletions src/flattenDeep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Infer deep flatted array.
*
* @typeParam T - input any array
* @returns deep flatted array
*
* @example
* ```ts
* FlattenDeep<[]> // []
* FlattenDeep<[[1, [2, [3, [4]], 5]]> // [1, 2, 3, 4, 5]
* ```
*
* @beta
*/
type FlattenDeep<T extends readonly unknown[]> = T extends readonly [
infer A,
...infer Rest
]
? A extends readonly unknown[]
? [...FlattenDeep<A>, ...FlattenDeep<Rest>]
: [A, ...FlattenDeep<Rest>]
: [...T]
/**
* Recursively flattens array.
*
* @param val - The `array` to flatten
* @returns The result of `val.flat(Infinity)`
*
* @example
* ```ts
* flattenDeep([]) // []
* flattenDeep([1, [2, [3, [4]], 5]]) // [1, 2, 3, 4, 5]
* ```
*
* @beta
*/
const flattenDeep = <T extends readonly unknown[]>(val: T): FlattenDeep<T> =>
val.flat(Infinity) as FlattenDeep<T>

export { flattenDeep }
export type { FlattenDeep }
67 changes: 67 additions & 0 deletions test/flattenDeep.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { assertEquals } from '../deps.ts'
import { FlattenDeep as Flat, flattenDeep } from '../src/flattenDeep.ts'
import { assertEqual } from './asserts.ts'
Deno.test('flattenDeep', () => {
const table: [unknown[], unknown[]][] = [
[[], []],
[[null], [null]],
[
[null, undefined, 1, 'hello'],
[null, undefined, 1, 'hello']
],
[[[]], []],
[[[1]], [1]],
[[[1, 2, 3]], [1, 2, 3]],
[[[1, 2, 3, undefined, null]], [1, 2, 3, undefined, null]],
[
[[1, 2, 3, undefined, null], 4, 5, 6],
[1, 2, 3, undefined, null, 4, 5, 6]
],
[
[
[1, 2, 3, undefined, null],
[4, 5, 6]
],
[1, 2, 3, undefined, null, 4, 5, 6]
],
[
[[1, 2, 3, undefined, ['hello', 4], null]],
[1, 2, 3, undefined, 'hello', 4, null]
],
[
[
'',
[1, 2, 3, undefined, ['hello', 4], null],
[5, 6, ['world']],
[[7, 8], 9]
],
['', 1, 2, 3, undefined, 'hello', 4, null, 5, 6, 'world', 7, 8, 9]
]
]
table.forEach(([val, expected]) => {
assertEquals(
flattenDeep(val),
expected,
`flattenDeep(${val}) -> ${expected}`
)
})
})

Deno.test('types', () => {
assertEqual<[], Flat<[]>>()
assertEqual<never[], Flat<never[]>>()
// TODO: Success this case
// assertEqual<never[], Flat<never[][]>>()
assertEqual<[''], Flat<['']>>()
assertEqual<[number], Flat<[number]>>()
assertEqual<[number, string], Flat<[number, string]>>()
assertEqual<number[], Flat<number[]>>()
assertEqual<(number | string)[], Flat<(number | string)[]>>()
assertEqual<readonly [''], Flat<readonly ['']>>()
assertEqual<readonly ['', 'hello'], Flat<readonly ['', 'hello']>>()
assertEqual<readonly ['', ''], Flat<readonly ['', readonly ['']]>>()
assertEqual<
readonly ['', '', 'hello'],
Flat<readonly ['', readonly ['', readonly ['hello']]]>
>()
})

0 comments on commit 7dadd6b

Please sign in to comment.