Currently, only functions that both take and return an Iterable (or AsyncIterable) are available as pipeable operators; functions that take an Iterable and return some "scalar" value are not.
This means that e.g. code that uses piping that needs to return an array - which is common in my codebase because very little third-party JS code works with Iterables - has to be written like this:
(Example is getting the keys of selected checkboxes from an Angular form.)
This can be worked around by using a utility library with a more generic pipe(), and in a future an unspecified time away may be made irrelevant by the upcoming native pipe operator proposals, but it'd be nice if Ix provided this in the meantime, given the overall benefits of piping for readability and chaining.
Using reduce() as an example function to be converted, I propose:
Adding a new operator type:
type TerminalOperator<T, R> = UnaryFunction<Iterable<T>, R>
Adding new overloads to pipe() that add a parameter of this type at the end, e.g.:
function pipe<T, A, R>(source: Iterable<T>, op1: OperatorFunction<T, A>, term: TerminalOperator<A, R>): R;
Adding operator versions of functions that take an Iterable as their first parameter but don't return an Iterable:
ix/iterable/operators/reduce.ts
import { reduce as _reduce } from '../reduce';
function reduce<T, R = T>(
accumulator: (previousValue: R, currentValue: T, currentIndex: number) => R,
seed?: R
): TerminalOperator<T, R> {
return function reduceOperatorFunction(source: Iterable<T>) {
return _reduce(source, accumulator, seed);
};
}
It's possible to eliminate some of the gruntwork in the last step by using a generic function like:
function toOperator<T, F extends (first: Iterable<T>, ...rest: any[]) => any>(
fn: F
): (...rest: any[]) => TerminalOperator<T, ReturnType<F>> {
return (...rest) => first => fn(first, ...rest);
but it seems impossible to use it as a workaround directly, Typescript is unable to infer the types correctly; therefore it's necessary to provide the actual signatures of the resulting operators for this to be of much use.
Given that this is mostly mechanical work, I might be up to actually contributing this if there's interest, but for obvious reasons I'd like to gauge that before making a huge PR.
Currently, only functions that both take and return an
Iterable
(orAsyncIterable
) are available as pipeable operators; functions that take anIterable
and return some "scalar" value are not.This means that e.g. code that uses piping that needs to return an array - which is common in my codebase because very little third-party JS code works with
Iterable
s - has to be written like this:as opposed to, hypothetically, like this:
(Example is getting the keys of selected checkboxes from an Angular form.)
This can be worked around by using a utility library with a more generic
pipe()
, and in a future an unspecified time away may be made irrelevant by the upcoming native pipe operator proposals, but it'd be nice if Ix provided this in the meantime, given the overall benefits of piping for readability and chaining.Using
reduce()
as an example function to be converted, I propose:pipe()
that add a parameter of this type at the end, e.g.:Iterable
as their first parameter but don't return anIterable
:ix/iterable/operators/reduce.ts
It's possible to eliminate some of the gruntwork in the last step by using a generic function like:
but it seems impossible to use it as a workaround directly, Typescript is unable to infer the types correctly; therefore it's necessary to provide the actual signatures of the resulting operators for this to be of much use.
Given that this is mostly mechanical work, I might be up to actually contributing this if there's interest, but for obvious reasons I'd like to gauge that before making a huge PR.