ix
Version:
The Interactive Extensions for JavaScript
41 lines (36 loc) • 1.5 kB
text/typescript
import { flatMap } from './flatmap.js';
import { AsyncIterableX } from '../asynciterablex.js';
import { isAsyncIterable } from '../../util/isiterable.js';
type Flattened<Arr, Depth extends number> = Depth extends -1
? FlattenInfinite<Arr>
: FlattenWithDepth<Arr, Depth>;
type FlattenInfinite<Arr> = Arr extends AsyncIterable<infer T> ? FlattenInfinite<T> : Arr;
type FlattenWithDepth<Arr, Depth extends number> = {
done: Arr;
recur: Arr extends AsyncIterable<infer T>
? FlattenWithDepth<
T,
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]
>
: Arr;
}[Depth extends -1 ? 'done' : 'recur'];
/**
* Flattens the nested async-iterable by the given depth.
*
* @template T The type of elements in the source sequence.
* @param {number} [depth=Infinity] The depth to flatten the async-iterable sequence if specified, otherwise infinite.
* @returns {MonoTypeOperatorAsyncFunction<T>} An operator that flattens the async-iterable sequence.
*/
export function flat<D extends number = -1>(depth: D = -1 as any, concurrent = Infinity) {
depth = (depth < 0 ? Infinity : depth) as any;
return function flattenOperatorFunction<T>(
source: AsyncIterable<T>
): AsyncIterableX<Flattened<T, D>> {
return flatMap((item: any) => {
if (isAsyncIterable(item)) {
return depth > 0 ? flat(depth - 1)(item) : item;
}
return [item];
}, concurrent)(source) as AsyncIterableX<Flattened<T, D>>;
};
}