lfi
Version:
A lazy functional iteration library supporting sync, async, and concurrent iteration.
1,787 lines (1,695 loc) • 171 kB
text/typescript
/** @internal */
type MaybePromiseLike<Value> = Value | PromiseLike<Value>
/** @internal */
type StrictNegative<Numeric extends number> = Numeric extends 0
? never
: `${Numeric}` extends `-${string}`
? Numeric
: never
/** @internal */
type NonNegative<Numeric extends number> = Numeric extends 0
? Numeric
: StrictNegative<Numeric> extends never
? Numeric
: never
/** @internal */
type StrictInteger<Numeric extends number> = `${Numeric}` extends `${bigint}`
? Numeric
: never
/** @internal */
type CheckNumericLiteral<
Numeric extends number,
LiteralNumber extends number,
> = number extends Numeric ? Numeric : LiteralNumber
/** @internal */
type Integer<Numeric extends number> = CheckNumericLiteral<
Numeric,
StrictInteger<Numeric>
>
/** @internal */
type NonNegativeInteger<Numeric extends number> = CheckNumericLiteral<
Numeric,
NonNegative<StrictInteger<Numeric>>
>
/** @internal */
type PositiveInteger<Numeric extends number> = CheckNumericLiteral<
Numeric,
NonNegative<StrictInteger<Numeric>>
>
/** @internal */
type Curried<Parameters extends readonly any[], Return> = <
PartialParameters extends Partial<Parameters>,
>(
...args: PartialParameters
) => PartialParameters extends Parameters
? Return
: Parameters extends readonly [
...TupleOfSameLength<PartialParameters>,
...infer RemainingParameters,
]
? RemainingParameters extends any[]
? Curried<RemainingParameters, Return>
: never
: never
/** @internal */
type TupleOfSameLength<Tuple extends readonly any[]> = Extract<
{ [Key in keyof Tuple]: any },
readonly any[]
>
/**
* Returns a curried version of `fn`.
*
* @example
* ```js
* function slothLog(a, b, c) {
* console.log(`${a} Sloth ${b} Sloth ${c}`)
* }
*
* const curriedSlothLog = curry(slothLog)
*
* console.log(curriedSlothLog.name)
* //=> slothLog
*
* console.log(curriedSlothLog.length)
* //=> 3
*
* curriedSlothLog(`Hello`, `World`, `!`)
* curriedSlothLog(`Hello`)(`World`, `!`)
* curriedSlothLog(`Hello`, `World`)(`!`)
* curriedSlothLog(`Hello`)(`World`)(`!`)
* //=> Hello Sloth World Sloth !
* //=> Hello Sloth World Sloth !
* //=> Hello Sloth World Sloth !
* //=> Hello Sloth World Sloth !
* ```
*
* @category Core
* @since v0.0.1
*/
declare const curry: <Parameters extends readonly any[], Return>(
fn: (...args: Parameters) => Return,
) => Curried<Parameters, Return>
/**
* Returns the result of piping `value` through the given functions.
*
* @example
* ```js
* console.log(
* pipe(
* `sloth`,
* name => `${name.toUpperCase()}!`,
* text => [text, text, text],
* array => array.join(` `),
* ),
* )
* // => SLOTH! SLOTH! SLOTH!
* ```
*
* @category Core
* @since v0.0.1
*/
declare const pipe: {
<Value>(value: Value): Value
<A, B>(value: A, fn: (a: A) => B): B
<A, B, C>(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C
<A, B, C, D>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
): D
<A, B, C, D, E>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
): E
<A, B, C, D, E, F>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
): F
<A, B, C, D, E, F, G>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
): G
<A, B, C, D, E, F, G, H>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
): H
<A, B, C, D, E, F, G, H, I>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
fn8: (h: H) => I,
): I
<A, B, C, D, E, F, G, H, I, J>(
value: A,
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
fn8: (h: H) => I,
fn9: (i: I) => J,
): J
}
/**
* Returns a function that takes a single parameter and pipes it through the
* given functions.
*
* @example
* ```js
* const screamify = compose(
* name => `${name.toUpperCase()}!`,
* text => [text, text, text],
* array => array.join(` `),
* )
*
* console.log(screamify(`sloth`))
* // => SLOTH! SLOTH! SLOTH!
* ```
*
* @category Core
* @since v0.0.2
*/
declare const compose: {
(): <Value>(value: Value) => Value
<A, B>(fn: (a: A) => B): (value: A) => B
<A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (value: A) => C
<A, B, C, D>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
): (value: A) => D
<A, B, C, D, E>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
): (value: A) => E
<A, B, C, D, E, F>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
): (value: A) => F
<A, B, C, D, E, F, G>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
): (value: A) => G
<A, B, C, D, E, F, G, H>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
): (value: A) => H
<A, B, C, D, E, F, G, H, I>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
fn8: (h: H) => I,
): (value: A) => I
<A, B, C, D, E, F, G, H, I, J>(
fn1: (a: A) => B,
fn2: (b: B) => C,
fn3: (c: C) => D,
fn4: (d: D) => E,
fn5: (e: E) => F,
fn6: (f: F) => G,
fn7: (g: G) => H,
fn8: (h: H) => I,
fn9: (i: I) => J,
): (value: A) => J
}
/**
* Returns an async iterable wrapper around `iterable`.
*
* Note that when passing a concur iterable the returned async iterable may have
* to buffer the values produced by the concur iterable because values may not
* be read from the async iterable as quickly as they are produced by the concur
* iterable. This is a fundamental problem because concur iterables are "push"
* based while async iterables are "pull" based, which creates backpressure.
*
* @example
* ```js
* const asyncIterable = asAsync([`sloth`, `more sloth`, `even more sloth`])
*
* console.log(typeof asyncIterable[Symbol.asyncIterator])
* //=> function
*
* for await (const value of asyncIterable) {
* console.log(value)
* }
* //=> sloth
* //=> more sloth
* //=> even more sloth
* ```
*
* @category Core
* @since v0.0.2
*/
declare const asAsync: <Value>(
iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>,
) => AsyncIterable<Value>
/**
* Represents a potentially lazy collection of values, each of type `Value`,
* that can be iterated over concurrently.
*
* The collection can be iterated by invoking the concur iterable with an
* `apply` callback. The callback is applied to each value in the collection,
* potentially asynchronously, in some order.
*
* Invoking the concur iterable returns a promise that resolves when `apply`
* has been applied to each value in the concur iterable and each result
* returned by `apply` is awaited.
*
* It is like an event emitter that accepts only one event handler and returns a
* promise that resolves when all events have been emitted and handled.
*
* @example
* ```js
* const slothNamesConcurIterable = pipe(
* asConcur(['sloth-names1.txt', 'sloth-names2.txt']),
* mapConcur(filename => fs.promises.readFile(filename, `utf8`)),
* flatMapConcur(content => content.split(`\n`)),
* )
* ```
*
* @category Core
* @since v0.0.2
*/
type ConcurIterable<Value> = (
apply: ConcurIterableApply<Value>,
) => Promise<void>
/**
* The callback invoked for each value of a {@link ConcurIterable}.
*
* @category Core
* @since v2.0.0
*/
type ConcurIterableApply<Value> = (
value: Value,
) => MaybePromiseLike<void>
/**
* Returns a concur iterable wrapper around `iterable`.
*
* @example
* ```js
* const concurIterable = asConcur([`sloth`, `more sloth`, `even more sloth`])
*
* await forEachConcur(console.log, concurIterable)
* //=> sloth
* //=> more sloth
* //=> even more sloth
* ```
*
* @category Core
* @since v0.0.2
*/
declare const asConcur: <Value>(
iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>,
) => ConcurIterable<Value>
/**
* An iterable that contains zero values.
*
* Can be used as an iterable of any type.
*
* Like `[]`, but opaque.
*
* @example
* ```js
* console.log([...empty])
* //=> []
* ```
*
* @category Core
* @since v0.0.1
*/
declare const empty: Iterable<any>
/**
* An async iterable that contains zero values.
*
* Can be used as an async iterable of any type.
*
* Like `[]`, but for async iterables.
*
* @example
* ```js
* console.log(await pipe(emptyAsync, reduceAsync(toArray())))
* //=> []
* ```
*
* @category Core
* @since v0.0.1
*/
declare const emptyAsync: AsyncIterable<any>
/**
* A concur iterable that contains zero values.
*
* Can be used as a concur iterable of any type.
*
* Like `[]`, but for concur iterables.
*
* @example
* ```js
* console.log(await pipe(emptyConcur, reduceConcur(toArray())))
* //=> []
* ```
*
* @category Core
* @since v0.0.2
*/
declare const emptyConcur: ConcurIterable<any>
/**
* Returns an iterable equivalent, but not referentially equal, to `iterable`.
*
* @category Core
* @since v2.0.0
*/
declare const opaque: <Value>(iterable: Iterable<Value>) => Iterable<Value>
/**
* Returns an async iterable equivalent, but not referentially equal, to
* `asyncIterable`.
*
* @category Core
* @since v2.0.0
*/
declare const opaqueAsync: <Value>(
asyncIterable: AsyncIterable<Value>,
) => AsyncIterable<Value>
/**
* Returns an concur iterable equivalent, but not referentially equal, to
* `concurIterable`.
*
* @category Core
* @since v2.0.0
*/
declare const opaqueConcur: <Value>(
concurIterable: ConcurIterable<Value>,
) => ConcurIterable<Value>
/**
* An iterable containing exactly zero or one values.
*
* @category Optionals
* @since v2.0.0
*/
type Optional<Value> = Iterable<Value>
/**
* An async iterable containing exactly zero or one values.
*
* @category Optionals
* @since v2.0.0
*/
type AsyncOptional<Value> = AsyncIterable<Value>
/**
* A concur iterable containing exactly zero or one values.
*
* @category Optionals
* @since v2.0.0
*/
type ConcurOptional<Value> = ConcurIterable<Value>
/**
* Returns the only value in `iterable` if it contains exactly one value.
* Otherwise, returns the result of invoking `fn`.
*
* @example
* ```js
* console.log(pipe([`sloth`], or(() => `Never called`)))
* //=> sloth
*
* console.log(pipe([], or(() => `I get called!`)))
* //=> I get called!
*
* console.log(pipe([1, `sloth`, 3], or(() => `I also get called!`)))
* //=> I also get called!
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const or: {
<Value>(fn: () => Value): (iterable: Iterable<Value>) => Value
<Value>(fn: () => Value, iterable: Iterable<Value>): Value
}
/**
* Returns a promise that resolves to the only value in `asyncIterable` if it
* contains exactly one value. Otherwise, returns a promise that resolves to
* the awaited result of invoking `fn`.
*
* @example
* ```js
* console.log(await pipe(asAsync([`sloth`]), orAsync(() => `Never called`)))
* //=> sloth
*
* console.log(await pipe(emptyAsync, orAsync(() => `I get called!`)))
* //=> I get called!
*
* console.log(
* await pipe(
* asAsync([1, `sloth`, 3]),
* orAsync(() => `I also get called!`),
* ),
* )
* //=> I also get called!
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const orAsync: {
<Value>(
fn: () => MaybePromiseLike<Value>,
): (asyncIterable: AsyncIterable<Value>) => Promise<Value>
<Value>(
fn: () => MaybePromiseLike<Value>,
asyncIterable: AsyncIterable<Value>,
): Promise<Value>
}
/**
* Returns a promise that resolves to the only value in `concurIterable` if it
* contains exactly one value. Otherwise, returns a promise that resolves to
* the awaited result of invoking `fn`.
*
* @example
* ```js
* console.log(await pipe(asConcur([`sloth`]), orConcur(() => `Never called`)))
* //=> sloth
*
* console.log(await pipe(emptyConcur, orConcur(() => `I get called!`)))
* //=> I get called!
*
* console.log(
* await pipe(
* asConcur([1, `sloth`, 3]),
* orConcur(() => `I also get called!`),
* ),
* )
* //=> I also get called!
* ```
*
* @category Optionals
* @since v0.0.2
*/
declare const orConcur: {
<Value>(
fn: () => MaybePromiseLike<Value>,
): (concurIterable: ConcurIterable<Value>) => Promise<Value>
<Value>(
fn: () => MaybePromiseLike<Value>,
concurIterable: ConcurIterable<Value>,
): Promise<Value>
}
/**
* Returns the only value in `iterable` if it contains exactly one value.
* Otherwise, throws an error.
*
* @example
* ```js
* console.log(get([`sloth`]))
* //=> sloth
*
* try {
* console.log(get([]))
* } catch {
* console.log(`Oh no! It was empty...`)
* }
* //=> Oh no! It was empty...
*
* try {
* console.log(get([1, `sloth`, 3]))
* } catch {
* console.log(`Oh no! It had more than one value...`)
* }
* //=> Oh no! It had more than one value...
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const get: <Value>(iterable: Iterable<Value>) => Value
/**
* Returns a promise that resolves to the only value in `asyncIterable` if it
* contains exactly one value. Otherwise, returns a promise that rejects.
*
* @example
* ```js
* console.log(await getAsync(asAsync([`sloth`])))
* //=> sloth
*
* try {
* console.log(await getAsync(emptyAsync))
* } catch {
* console.log(`Oh no! It was empty...`)
* }
* //=> Oh no! It was empty...
*
* try {
* console.log(await getAsync(asAsync([1, `sloth`, 3])))
* } catch {
* console.log(`Oh no! It had more than one value...`)
* }
* //=> Oh no! It had more than one value...
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const getAsync: <Value>(
asyncIterable: AsyncIterable<Value>,
) => Promise<Value>
/**
* Returns a promise that resolves to the only value in `concurIterable` if it
* contains exactly one value. Otherwise, returns a promise that rejects.
*
* @example
* ```js
* console.log(await getConcur(asConcur([`sloth`])))
* //=> sloth
*
* try {
* console.log(await getConcur(emptyConcur))
* } catch {
* console.log(`Oh no! It was empty...`)
* }
* //=> Oh no! It was empty...
*
* try {
* console.log(await getConcur(asConcur([1, `sloth`, 3])))
* } catch {
* console.log(`Oh no! It had more than one value...`)
* }
* //=> Oh no! It had more than one value...
* ```
*
* @category Optionals
* @since v0.0.2
*/
declare const getConcur: <Value>(
concurIterable: ConcurIterable<Value>,
) => Promise<Value>
/**
* Returns a pair of iterables. If `iterable` is empty, then both of the
* returned iterables are empty. Otherwise, the first iterable contains the
* first value of `iterable` and the second iterable contains the rest of the
* values of `iterable`. The second iterable can only be iterated once.
*
* @example
* ```js
* const slothActivities = [`sleeping`, `yawning`, `eating`]
* const [first, rest] = next(slothActivities)
*
* console.log(get(first))
* //=> sleeping
*
* console.log([...rest])
* //=> [ 'yawning', 'eating' ]
*
* const badThingsAboutSloths = []
* const [first2, rest2] = next(badThingsAboutSloths)
*
* console.log(count(first2))
* //=> 0
*
* console.log(count(rest2))
* //=> 0
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const next: <Value>(
iterable: Iterable<Value>,
) => [Optional<Value>, Iterable<Value>]
/**
* Returns a promise that resolves to a pair of async iterables. If
* `asyncIterable` is empty, then both of the returned async iterables are
* empty. Otherwise, the first async iterable contains the first value of
* `asyncIterable` and the second async iterable contains the rest of the values
* of `asyncIterable`. The second async iterable can only be iterated once.
*
* @example
* ```js
* const slothActivities = asAsync([`sleeping`, `yawning`, `eating`])
* const [first, rest] = await nextAsync(slothActivities)
*
* console.log(await getAsync(first))
* //=> sleeping
*
* console.log(await reduceAsync(toArray(), rest))
* //=> [ 'yawning', 'eating' ]
*
* const badThingsAboutSloths = emptyAsync
* const [first2, rest2] = await nextAsync(badThingsAboutSloths)
*
* console.log(await countAsync(first2))
* //=> 0
*
* console.log(await countAsync(rest2))
* //=> 0
* ```
*
* @category Optionals
* @since v0.0.1
*/
declare const nextAsync: <Value>(
asyncIterable: AsyncIterable<Value>,
) => Promise<[AsyncOptional<Value>, AsyncIterable<Value>]>
/**
* A reducer that reduces by combining pairs of values using function
* application.
*
* @category Reducers
* @since v2.0.0
*/
type FunctionReducer<Value = unknown> = (
acc: Value,
value: Value,
) => Value
/**
* A reducer that reduces by combining pairs of values using
* {@link RawOptionalReducerWithoutFinish.add}.
*
* @category Reducers
* @since v2.0.0
*/
type RawOptionalReducerWithoutFinish<Value = unknown, This = unknown> = {
add: (this: This, acc: Value, value: Value) => Value
}
/**
* A reducer that reduces by combining pairs of values using
* {@link RawOptionalReducerWithFinish.add} and then tranforming the final value
* using {@link RawOptionalReducerWithFinish.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type RawOptionalReducerWithFinish<
Value = unknown,
Finished = Value,
This = unknown,
> = RawOptionalReducerWithoutFinish<Value, This> & {
finish: (this: This, acc: Value) => Finished
}
/**
* A reducer that reduces by combining pairs of values using
* {@link OptionalReducer.add} and then tranforming the final value using
* {@link OptionalReducer.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type OptionalReducer<
Value = unknown,
Finished = Value,
> = RawOptionalReducerWithFinish<Value, Finished>
/**
* A reducer that reduces by creating an initial accumulator using
* {@link RawReducerWithoutFinish.create} and then adding values to the
* accumulator values using {@link RawReducerWithoutFinish.add}.
*
* @category Reducers
* @since v2.0.0
*/
type RawReducerWithoutFinish<
Value = unknown,
Acc = Value,
This = unknown,
> = {
create: (this: This) => Acc
add: (this: This, acc: Acc, value: Value) => Acc
}
/**
* A reducer that reduces by creating an initial accumulator using
* {@link RawReducerWithFinish.create}, then adding values to the accumulator
* values using {@link RawReducerWithFinish.add}, and then tranforming the final
* accumulator using {@link RawReducerWithFinish.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type RawReducerWithFinish<
Value = unknown,
Acc = Value,
Finished = Acc,
This = unknown,
> = RawReducerWithoutFinish<Value, Acc, This> & {
finish: (this: This, acc: Acc) => Finished
}
/**
* A reducer that reduces by creating an initial accumulator using
* {@link Reducer.create}, then adding values to the accumulator values using
* {@link Reducer.add}, and then tranforming the final accumulator using
* {@link Reducer.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type Reducer<
Value = unknown,
Acc = Value,
Finished = Acc,
> = RawReducerWithFinish<Value, Acc, Finished>
/**
* A keyed reducer that reduces by creating an initial accumulator using
* {@link RawKeyedReducer.create} and then adding key-value pairs to the
* accumulator values using {@link RawKeyedReducer.add}. The accumulator can be
* queried for values by key using {@link RawKeyedReducer.get}.
*
* @category Reducers
* @since v2.0.0
*/
type RawKeyedReducer<
Key = unknown,
Value = unknown,
Acc = [Key, Value],
This = unknown,
> = RawReducerWithoutFinish<readonly [Key, Value], Acc, This> & {
get: (this: This, acc: Acc, key: Key) => Value | typeof NO_ENTRY
}
/**
* A keyed reducer that reduces by creating an initial accumulator using
* {@link KeyedReducer.create} and then adding key-value pairs to the
* accumulator values using {@link KeyedReducer.add}. The accumulator can be
* queried for values by key using {@link KeyedReducer.get}.
*
* @category Reducers
* @since v2.0.0
*/
type KeyedReducer<
Key = unknown,
Value = unknown,
Acc = [Key, Value],
> = RawKeyedReducer<Key, Value, Acc>
/**
* An async reducer that reduces by combining pairs of values using function
* application.
*
* @category Reducers
* @since v2.0.0
*/
type AsyncFunctionReducer<Value = unknown> = (
acc: Value,
value: Value,
) => MaybePromiseLike<Value>
/**
* An async reducer that reduces by combining pairs of values using
* {@link RawAsyncOptionalReducerWithoutFinish.add}.
*
* @category Reducers
* @since v2.0.0
*/
type RawAsyncOptionalReducerWithoutFinish<
Value = unknown,
This = unknown,
> = {
add: (this: This, acc: Value, value: Value) => MaybePromiseLike<Value>
}
/**
* An async reducer that reduces by combining pairs of values using
* {@link RawAsyncOptionalReducerWithFinish.add} and then tranforming the final
* value using {@link RawAsyncOptionalReducerWithFinish.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type RawAsyncOptionalReducerWithFinish<
Value = unknown,
Finished = Value,
This = unknown,
> = RawAsyncOptionalReducerWithoutFinish<Value, This> & {
finish: (this: This, acc: Value) => MaybePromiseLike<Finished>
}
/**
* An async reducer that reduces by combining pairs of values using
* {@link AsyncOptionalReducer.add} and then tranforming the final value using
* {@link AsyncOptionalReducer.finish}.
*
* @category Reducers
* @since v2.0.0
*/
type AsyncOptionalReducer<
Value = unknown,
Finished = Value,
> = RawAsyncOptionalReducerWithFinish<Value, Finished>
/**
* An async reducer that reduces by creating an initial accumulator using
* {@link RawAsyncReducerWithoutFinish.create} and then adding values to the
* accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The async
* reducer is optionally able to combine pairs of accumulators using
* {@link RawAsyncReducerWithoutFinish.combine}.
*
* @category Reducers
* @since v2.0.0
*/
type RawAsyncReducerWithoutFinish<
Value = unknown,
Acc = Value,
This = unknown,
> = {
create: (this: This) => MaybePromiseLike<Acc>
add: (this: This, acc: Acc, value: Value) => MaybePromiseLike<Acc>
combine?: (this: This, acc1: Acc, acc2: Acc) => MaybePromiseLike<Acc>
}
/**
* An async reducer that reduces by creating an initial accumulator using
* {@link RawAsyncReducerWithFinish.create}, then adding values to the
* accumulator values using {@link RawAsyncReducerWithFinish.add}, and then
* tranforming the final accumulator using
* {@link RawAsyncReducerWithFinish.finish}. The async
* reducer is optionally able to combine pairs of accumulators using
* {@link RawAsyncReducerWithFinish.combine}.
*
* @category Reducers
* @since v2.0.0
*/
type RawAsyncReducerWithFinish<
Value = unknown,
Acc = Value,
Finished = Acc,
This = unknown,
> = RawAsyncReducerWithoutFinish<Value, Acc, This> & {
finish: (this: This, acc: Acc) => MaybePromiseLike<Finished>
}
/**
* An async reducer that reduces by creating an initial accumulator using
* {@link AsyncReducer.create}, then adding values to the accumulator values
* using {@link AsyncReducer.add}, and then tranforming the final accumulator
* using {@link AsyncReducer.finish}. The async reducer is optionally able to
* combine pairs of accumulators using {@link AsyncReducer.combine}.
*
* @category Reducers
* @since v2.0.0
*/
type AsyncReducer<
Value = unknown,
Acc = Value,
Finished = Acc,
> = RawAsyncReducerWithFinish<Value, Acc, Finished>
/**
* An async keyed reducer that reduces by creating an initial accumulator using
* {@link RawAsyncKeyedReducer.create} and then adding key-value pairs to the
* accumulator values using {@link RawAsyncKeyedReducer.add}. The async keyed
* reducer is optionally able to combine pairs of accumulators using
* {@link RawAsyncKeyedReducer.combine}. The accumulator can be queried for
* values by key using {@link RawAsyncKeyedReducer.get}.
*
* @category Reducers
* @since v2.0.0
*/
type RawAsyncKeyedReducer<
Key = unknown,
Value = unknown,
Acc = [Key, Value],
This = unknown,
> = RawAsyncReducerWithoutFinish<readonly [Key, Value], Acc, This> & {
get: (
this: This,
acc: Acc,
key: Key,
) => MaybePromiseLike<Value | typeof NO_ENTRY>
}
/**
* An async keyed reducer that reduces by creating an initial accumulator using
* {@link AsyncKeyedReducer.create} and then adding key-value pairs to the
* accumulator values using {@link AsyncKeyedReducer.add}. The async keyed
* reducer is optionally able to combine pairs of accumulators using
* {@link AsyncKeyedReducer.combine}. The accumulator can be queried for values
* by key using {@link AsyncKeyedReducer.get}.
*
* @category Reducers
* @since v2.0.0
*/
type AsyncKeyedReducer<
Key = unknown,
Value = unknown,
Acc = [Key, Value],
> = RawAsyncKeyedReducer<Key, Value, Acc>
/**
* A unique value representing the lack of an entry for some key in a
* {@link KeyedReducer} or {@link AsyncKeyedReducer}.
*
* Keyed reducers use this instead of `null` or `undefined` because they are
* valid values. Furthermore, introducing a `has` method for the purpose of
* disambiguation would be less performant due to the need to perform the lookup
* twice when the entry exists: `has` followed by `get` for the same key.
*
* @category Reducers
* @since v2.0.0
*/
declare const NO_ENTRY: unique symbol
/**
* Returns a {@link Reducer} or {@link OptionalReducer} equivalent to `reducer`
* except its final value is transformed using `fn`.
*
* @category Reducers
* @since v2.0.0
*/
declare const mapReducer: {
<Value, Acc, From, To, This>(
fn: (value: From) => To,
reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>,
): Reducer<Value, Acc, To>
<From, To>(
fn: (value: From) => To,
): <Value, Acc, This>(
reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>,
) => Reducer<Value, Acc, To>
<Value, From, To, This>(
fn: (value: From) => To,
reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>,
): Reducer<Value, To>
<From, To>(
fn: (value: From) => To,
): <Value, This>(
reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>,
) => Reducer<Value, To>
<Value, From, To, This>(
fn: (value: From) => To,
reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>,
): OptionalReducer<Value, To>
<From, To>(
fn: (value: From) => To,
): <Value, This>(
reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>,
) => OptionalReducer<Value, To>
<From, To, This>(
fn: (value: From) => To,
reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>,
): OptionalReducer<To>
<From, To>(
fn: (value: From) => To,
): <This>(
reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>,
) => OptionalReducer<To>
<From, To>(
fn: (value: From) => To,
reducer: FunctionReducer<From>,
): OptionalReducer<To>
<From, To>(
fn: (value: From) => To,
): (reducer: FunctionReducer<From>) => OptionalReducer<To>
}
/**
* Returns an {@link AsyncReducer} equivalent to `reducer` except its final
* value is transformed using `fn`.
*
* @category Reducers
* @since v2.0.0
*/
declare const mapAsyncReducer: {
<Value, Acc, From, To, This>(
fn: (value: From) => MaybePromiseLike<To>,
asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>,
): AsyncReducer<Value, Acc, To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
): <Value, Acc, This>(
asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>,
) => AsyncReducer<Value, Acc, To>
<Value, From, To, This>(
fn: (value: From) => MaybePromiseLike<To>,
asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>,
): AsyncReducer<Value, To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
): <Value, This>(
asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>,
) => AsyncReducer<Value, To>
<Value, From, To, This>(
fn: (value: From) => MaybePromiseLike<To>,
asyncReducer: Readonly<
RawAsyncOptionalReducerWithFinish<Value, From, This>
>,
): AsyncOptionalReducer<Value, To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
): <Value, This>(
asyncReducer: Readonly<
RawAsyncOptionalReducerWithFinish<Value, From, This>
>,
) => AsyncOptionalReducer<Value, To>
<From, To, This>(
fn: (value: From) => MaybePromiseLike<To>,
asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>,
): AsyncOptionalReducer<To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
): <This>(
asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>,
) => AsyncOptionalReducer<To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
asyncReducer: AsyncFunctionReducer<From>,
): AsyncOptionalReducer<To>
<From, To>(
fn: (value: From) => MaybePromiseLike<To>,
): (asyncReducer: AsyncFunctionReducer<From>) => AsyncOptionalReducer<To>
}
/**
* Returns a non-raw version of `reducer`.
*
* @category Reducers
* @since v2.0.0
*/
declare const normalizeReducer: {
<Key, Value, Acc, This>(
reducer: Readonly<RawKeyedReducer<Key, Value, Acc, This>>,
): KeyedReducer<Key, Value, Acc>
<Value, Acc, Finished, This>(
reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>,
): Reducer<Value, Acc, Finished>
<Value, Acc, This>(
reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>,
): Reducer<Value, Acc>
<Value, Finished, This>(
reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>,
): OptionalReducer<Value, Finished>
<Value, This>(
reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>,
): OptionalReducer<Value>
<Value>(reducer: FunctionReducer<Value>): OptionalReducer<Value>
<Key, Value, Acc, This>(
reducer: Readonly<RawAsyncKeyedReducer<Key, Value, Acc, This>>,
): AsyncKeyedReducer<Key, Value, Acc>
<Value, Acc, Finished, This>(
reducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, Finished, This>>,
): AsyncReducer<Value, Acc, Finished>
<Value, Acc, This>(
reducer: Readonly<RawAsyncReducerWithoutFinish<Value, Acc, This>>,
): AsyncReducer<Value, Acc>
<Value, Finished, This>(
reducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, Finished, This>>,
): AsyncOptionalReducer<Value, Finished>
<Value, This>(
reducer: Readonly<RawAsyncOptionalReducerWithoutFinish<Value, This>>,
): AsyncOptionalReducer<Value>
<Value>(reducer: AsyncFunctionReducer<Value>): AsyncOptionalReducer<Value>
}
/**
* Returns the result of reducing `iterable` using `reducer`.
*
* An initial accumulator is created using {@link Reducer.create}. Then each
* value in `iterable` is added to the accumulator and the current accumulator
* is updated using {@link Reducer.add}. Finally, the resulting accumulator is
* transformed using {@link Reducer.finish} if specified.
*
* If `reducer` is an optional reducer (no {@link Reducer.create} method), then
* an empty iterable is returned if `iterable` is empty. Otherwise, an iterable
* containing the result of reducing using the first value of the iterable as
* the initial accumulator is returned.
*
* Like `Array.prototype.reduce`, but for iterables.
*
* @example
* ```js
* console.log(
* pipe(
* [`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
* reduce((a, b) => `${a} ${b}`),
* get,
* ),
* )
* //=> Hello Sloth! What an interesting program!
*
* console.log(
* pipe(
* [`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
* reduce({ create: () => ``, add: (a, b) => `${a} ${b}` }),
* ),
* )
* //=> Hello Sloth! What an interesting program!
* ```
*
* @category Reducers
* @since v0.0.1
*/
declare const reduce: {
<Value, Acc, Finished, This>(
reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>,
iterable: Iterable<Value>,
): Finished
<Value, Acc, Finished, This>(
reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>,
): (iterable: Iterable<Value>) => Finished
<Value, Acc, This>(
reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>,
iterable: Iterable<Value>,
): Acc
<Value, Acc, This>(
reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>,
): (iterable: Iterable<Value>) => Acc
<Value, Finished, This>(
reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>,
iterable: Iterable<Value>,
): Optional<Finished>
<Value, Finished, This>(
reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>,
): (iterable: Iterable<Value>) => Optional<Finished>
<Value, This>(
reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>,
iterable: Iterable<Value>,
): Optional<Value>
<Value, This>(
reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>,
): (iterable: Iterable<Value>) => Optional<Value>
<Value>(
reducer: FunctionReducer<Value>,
iterable: Iterable<Value>,
): Optional<Value>
<Value>(
reducer: FunctionReducer<Value>,
): (iterable: Iterable<Value>) => Optional<Value>
}
/**
* Returns the result of reducing the `asyncIterable` using `asyncReducer`.
*
* Informally, an initial accumulator is created using
* {@link AsyncReducer.create}. Then each value in `asyncIterable` is added to
* the accumulator and the current accumulator is updated using
* {@link AsyncReducer.add}. Finally, the resulting accumulator is transformed
* using {@link AsyncReducer.finish} if specified. Multiple accumulators may be
* created, added to, and then combined if supported via
* {@link AsyncReducer.combine} and the next value of `asyncIterable` is ready
* before promises from {@link AsyncReducer.add} resolve.
*
* If `asyncReducer` is an async optional reducer (no
* {@link AsyncReducer.create} method), then an empty async iterable is returned
* if `asyncIterable` is empty. Otherwise, an async iterable containing the
* result of reducing using the first value of the async iterable as the initial
* accumulator is returned.
*
* Like `Array.prototype.reduce`, but for async iterables.
*
* @example
* ```js
* console.log(
* await pipe(
* asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
* reduceAsync((a, b) => `${a} ${b}`),
* getAsync,
* ),
* )
* //=> Hello World! What an interesting program!
*
* console.log(
* await pipe(
* asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
* reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
* ),
* )
* //=> Hello World! What an interesting program!
* ```
*
* @category Reducers
* @since v0.0.1
*/
declare const reduceAsync: {
<Value, Acc, Finished, This>(
asyncReducer:
| RawAsyncReducerWithFinish<Value, Acc, Finished, This>
| RawReducerWithFinish<Value, Acc, Finished, This>,
asyncIterable: AsyncIterable<Value>,
): Promise<Finished>
<Value, Acc, Finished, This>(
asyncReducer:
| RawAsyncReducerWithFinish<Value, Acc, Finished, This>
| RawReducerWithFinish<Value, Acc, Finished, This>,
): (asyncIterable: AsyncIterable<Value>) => Promise<Finished>
<Value, Acc, This>(
asyncReducer:
| RawAsyncReducerWithoutFinish<Value, Acc, This>
| RawReducerWithoutFinish<Value, Acc, This>,
asyncIterable: AsyncIterable<Value>,
): Promise<Acc>
<Value, Acc, This>(
asyncReducer:
| RawAsyncReducerWithoutFinish<Value, Acc, This>
| RawReducerWithoutFinish<Value, Acc, This>,
): (asyncIterable: AsyncIterable<Value>) => Promise<Acc>
<Value, Finished, This>(
asyncReducer:
| RawAsyncOptionalReducerWithFinish<Value, Finished, This>
| RawOptionalReducerWithFinish<Value, Finished, This>,
asyncIterable: AsyncIterable<Value>,
): AsyncOptional<Finished>
<Value, Finished, This>(
asyncReducer:
| RawAsyncOptionalReducerWithFinish<Value, Finished, This>
| RawOptionalReducerWithFinish<Value, Finished, This>,
): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Finished>
<Value, This>(
asyncReducer:
| RawAsyncOptionalReducerWithoutFinish<Value, This>
| RawOptionalReducerWithoutFinish<Value, This>,
asyncIterable: AsyncIterable<Value>,
): AsyncOptional<Value>
<Value, This>(
asyncReducer:
| RawAsyncOptionalReducerWithoutFinish<Value, This>
| RawOptionalReducerWithoutFinish<Value, This>,
): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>
<Value>(
asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>,
asyncIterable: AsyncIterable<Value>,
): AsyncOptional<Value>
<Value>(
asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>,
): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>
}
/**
* Returns the result of reducing the `concurIterable` using `asyncReducer`.
*
* Informally, an initial accumulator is created using
* {@link AsyncReducer.create}. Then each value in `concurIterable` is added to
* the accumulator and the current accumulator is updated using
* {@link AsyncReducer.add}. Finally, the resulting accumulator is transformed
* using {@link AsyncReducer.finish} if specified. Multiple accumulators may be
* created, added to, and then combined if supported via
* {@link AsyncReducer.combine} and the next value of `concurIterable` is ready
* before promises from {@link AsyncReducer.add} resolve.
*
* If `asyncReducer` is an async optional reducer (no
* {@link AsyncReducer.create} method), then an empty concur iterable is
* returned if `concurIterable` is empty. Otherwise, an concur iterable
* containing the result of reducing using the first value of the concur
* iterable as the initial accumulator is returned.
*
* Like `Array.prototype.reduce`, but for concur iterables.
*
* @example
* ```js
* console.log(
* await pipe(
* asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
* reduceAsync((a, b) => `${a} ${b}`),
* getAsync,
* ),
* )
* //=> Hello World! What an interesting program!
*
* console.log(
* await pipe(
* asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
* reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
* ),
* )
* //=> Hello World! What an interesting program!
* ```
*
* @category Reducers
* @since v0.0.1
*/
declare const reduceConcur: {
<Value, Acc, Finished, This>(
asyncReducer:
| RawAsyncReducerWithFinish<Value, Acc, Finished, This>
| RawReducerWithFinish<Value, Acc, Finished, This>,
concurIterable: ConcurIterable<Value>,
): Promise<Finished>
<Value, Acc, Finished, This>(
asyncReducer:
| RawAsyncReducerWithFinish<Value, Acc, Finished, This>
| RawReducerWithFinish<Value, Acc, Finished, This>,
): (concurIterable: ConcurIterable<Value>) => Promise<Finished>
<Value, Acc, This>(
asyncReducer:
| RawAsyncReducerWithoutFinish<Value, Acc, This>
| RawReducerWithoutFinish<Value, Acc, This>,
concurIterable: ConcurIterable<Value>,
): Promise<Acc>
<Value, Acc, This>(
asyncReducer:
| RawAsyncReducerWithoutFinish<Value, Acc, This>
| RawReducerWithoutFinish<Value, Acc, This>,
): (concurIterable: ConcurIterable<Value>) => Promise<Acc>
<Value, Finished, This>(
asyncReducer:
| RawAsyncOptionalReducerWithFinish<Value, Finished, This>
| RawOptionalReducerWithFinish<Value, Finished, This>,
concurIterable: ConcurIterable<Value>,
): ConcurOptional<Finished>
<Value, Finished, This>(
asyncReducer:
| RawAsyncOptionalReducerWithFinish<Value, Finished, This>
| RawOptionalReducerWithFinish<Value, Finished, This>,
): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Finished>
<Value, This>(
asyncReducer:
| RawAsyncOptionalReducerWithoutFinish<Value, This>
| RawOptionalReducerWithoutFinish<Value, This>,
concurIterable: ConcurIterable<Value>,
): ConcurOptional<Value>
<Value, This>(
asyncReducer:
| RawAsyncOptionalReducerWithoutFinish<Value, This>
| RawOptionalReducerWithoutFinish<Value, This>,
): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>
<Value>(
asyncReducer: FunctionReducer<Value> | AsyncFunctionReducer<Value>,
concurIterable: ConcurIterable<Value>,
): ConcurOptional<Value>
<Value>(
asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>,
): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>
}
/**
* Returns a {@link Reducer} that collects values to an `Array`.
*
* @example
* ```js
* console.log(
* pipe(
* cycle([`sloth`, `more sloth`]),
* take(4),
* reduce(toArray()),
* ),
* )
* //=> [ 'sloth', 'more sloth', 'sloth', 'more sloth' ]
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toArray: <Value>() => Reducer<Value, Value[]>
/**
* Returns a {@link Reducer} that collects values to a `Set`.
*
* @example
* ```js
* console.log(
* pipe(
* cycle([`sloth`, `more sloth`]),
* take(4),
* reduce(toArray()),
* ),
* )
* //=> Set(2) { 'sloth', 'more sloth' }
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toSet: <Value>() => Reducer<Value, Set<Value>>
/**
* Returns a {@link Reducer} that collects objects to a `WeakSet`.
*
* @example
* ```js
* console.log(
* pipe(
* cycle([`sloth`, `more sloth`]),
* take(4),
* map(string => ({ sloth: string })),
* reduce(toWeakSet()),
* ),
* )
* //=> WeakSet { <items unknown> }
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toWeakSet: <Value extends object>() => Reducer<
Value,
WeakSet<Value>
>
/**
* Returns a {@link KeyedReducer} that collects key-value pairs to an object.
*
* In the case of pairs with duplicate keys, the value of the last one wins.
*
* @example
* ```js
* console.log(
* pipe(
* [`sloth`, `more sloth`, `even more sloth`],
* map(string => [string, string.length]),
* reduce(toObject()),
* ),
* )
* //=> { sloth: 5, 'more sloth': 10, 'even more sloth': 15 }
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toObject: <Key extends keyof never, Value>() => RawKeyedReducer<
Key,
Value,
Record<Key, Value>
>
/**
* Returns a {@link KeyedReducer} that collects key-value pairs to a `Map`.
*
* In the case of pairs with duplicate keys, the value of the last one wins.
*
* @example
* ```js
* console.log(
* pipe(
* [`sloth`, `more sloth`, `even more sloth`],
* map(string => [string, string.length]),
* reduce(toMap()),
* ),
* )
* //=> Map(3) { 'sloth' => 5, 'more sloth' => 10, 'even more sloth' => 15 }
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toMap: <Key, Value>() => RawKeyedReducer<
Key,
Value,
Map<Key, Value>
>
/**
* Returns a {@link KeyedReducer} that collects key-value pairs to a `WeakMap`.
*
* In the case of pairs with duplicate keys, the value of the last one wins.
*
* @example
* ```js
* console.log(
* pipe(
* [`sloth`, `more sloth`, `even more sloth`],
* map(string => [{ sloth: string }, string.length]),
* reduce(toWeakMap()),
* ),
* )
* //=> WeakMap { <items unknown> }
* ```
*
* @category Collections
* @since v0.0.1
*/
declare const toWeakMap: <Key extends object, Value>() => RawKeyedReducer<
Key,
Value,
WeakMap<Key, Value>
>
/**
* Returns a {@link Reducer} that reduces key-value pairs using `outerReducer`
* and reduces values with the same key using `innerReducer`.
*
* @example
* ```js
* console.log(
* pipe(
* [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
* map(string => [string.length, string]),
* reduce(toGrouped(toArray(), toMap())),
* ),
* )
* //=> Map(3) {
* //=> 5 => [ 'sloth', 'sleep' ],
* //=> 10 => [ 'some sloth', 'more sloth' ],
* //=> 15 => [ 'even more sloth' ]
* //=> }
* ```
*
* @category Collections
* @since v2.0.0
*/
declare const toGrouped: {
<Key, Value, InnerAcc, InnerFinished, InnerThis, OuterAcc, OuterThis>(
innerReducer: Readonly<
RawReducerWithFinish<Value, InnerAcc, InnerFinished, InnerThis>
>,
outerReducer: Readonly<
RawKeyedReducer<Key, InnerAcc | InnerFinished, OuterAcc, OuterThis>
>,
): Reducer<readonly [Key, Value], never, OuterAcc>
<Value, InnerAcc, InnerFinished, InnerThis>(
innerReducer: Readonly<
RawReducerWithFinish<Value, InnerAcc, InnerFinished, InnerThis>
>,
): <Key, OuterAcc, OuterThis>(
outerReducer: Readonly<
RawKeyedReducer<Key, InnerAcc | InnerFinished, OuterAcc, OuterThis>
>,
) => Reducer<readonly [Key, Value], never, OuterAcc>
<Key, Value, InnerAcc, InnerThis, OuterAcc, OuterThis>(
innerReducer: Readonly<RawReducerWithoutFinish<Value, InnerAcc, InnerThis>>,
outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc, OuterAcc, OuterThis>>,
): Reducer<readonly [Key, Value], never, OuterAcc>
<Value, InnerAcc, InnerThis>(
innerReducer: Readonly<RawReducerWithoutFinish<Value, InnerAcc, InnerThis>>,
): <Key, OuterAcc, OuterThis>(
outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc, OuterAcc, OuterThis>>,
) => Reducer<readonly [Key, Value], never, OuterAcc>
<Key, Value, InnerFinished, InnerThis, OuterAcc, OuterThis>(
innerReducer: Readonly<
RawOptionalReducerWithFinish<Value, InnerFinished, InnerThis>
>,
outerReducer: Readonly<
RawKeyedReducer<Key, Value | InnerFinished, OuterAcc, OuterThis>
>,
): Reducer<readonly [Key, Value], never, OuterAcc>
<Value, InnerFinished, InnerThis>(
innerReducer: Readonly<
RawOptionalReducerWithFinish<Value, InnerFinished, InnerThis>
>,
): <Key, OuterAcc, OuterThis>(
outerReducer: Readonly<
RawKeyedReducer<Key, Value | InnerFinished, OuterAcc, OuterThis>
>,
) => Reducer<readonly [Key, Value], never, OuterAcc>
<Key, Value, InnerThis, OuterAcc, OuterThis>(
innerReducer: Readonly<RawOptionalReducerWithoutFinish<Value, InnerThis>>,
outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>,
): Reducer<readonly [Key, Value], never, OuterAcc>
<Value, InnerThis>(
innerReducer: Readonly<RawOptionalReducerWithoutFinish<Value, InnerThis>>,
): <Key, OuterAcc, OuterThis>(
outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>,
) => Reducer<readonly [Key, Value], never, OuterAcc>
<Key, Value, OuterAcc, OuterThis>(
innerReducer: FunctionReducer<Value>,
outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>,
): Reducer<readonly [Key, Value], never, OuterAcc>
<Value>(
innerReducer: FunctionReducer<Value>,
): <Key, OuterAcc, OuterThis>(
outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>,
) => Reducer<readonly [Key, Value], never, OuterAcc>
}
/**
* Returns a {@link Reducer} or {@link OptionalReducer} that reduces values to
* an object or array of the same shape as `reducers` using all of the reducers
* in `reducers`.
*
* Returns an {@link OptionalReducer} if at least one of the input reducers is
* an {@link OptionalReducer}. Otherwise, returns a {@link Reducer}.
*
* @example
* ```js
* console.log(
* pipe(
* [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
* map(string => string.length),
* reduce(toMultiple([toSet(), toCount(), toJoin(`,`)])),
* ),
* )
* //=> [ Set(3) { 5, 10, 15 }, 5, '5,10,5,10,15' ]
*
* console.log(
* pipe(
* [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
* map(string => string.length),
* reduce(
* toMultiple({
* set: toSet(),
* count: toCount(),
* string: toJoin(`,`),
* }),
* ),
* ),
* )
* //=> { set: Set(3) { 5, 10, 15 }, count: 5, string: '5,10,5,10,15' }
* ```
*
* @category Collections
* @since v2.0.0
*/
declare const toMultiple: {
<
Value,
Reducers extends
| readonly [RawReducerWithoutFinish<Value, any>]
| readonly RawReducerWithoutFinish<Value, any>[]
| Readonly<Record<keyof never, RawReducerWithoutFinish<Value, any>>>,
>(
reducers: Reducers,
): Reducer<
Value,
{
-readonly [Key in keyof Reducers]: Reducers[Key] extends RawReducerWithoutFinish<
Value,
infer Acc
>
? Acc
: never
},
{
-readonly [Key in keyof Reducers]: Reducers[Key] extends RawReducerWithFinish<
Value,
any,
infer Finished
>
? Finished
: Reducers[Key] extends RawReducerWithoutFinish<Value, infer Acc>
? Acc
: never
}
>
<
Value,
Reducers extends
| readonly [
| RawReducerWithoutFinish<Value, any>
| RawOptionalReducerWithoutFinish<Value>
| FunctionReducer<Value>,
]
| readonly (
| RawReducerWithoutFinish<Value, any>
| RawOptionalReducerWithoutFinish<Value>
| FunctionReducer<Value>
)[]
| Readonly<
Reco