Skip to content

Commit

Permalink
feat(filter): rewrite filter implementation to support type-guards …
Browse files Browse the repository at this point in the history
…as predicates

...also relaxes the type returned by `IndexedPredicate` to be `unknown`
  • Loading branch information
biggyspender committed Jan 23, 2023
1 parent 3b66fce commit f562868
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 23 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"rmrf",
"socio",
"ts-iterable-functions",
"undefer",
"Vauxhall"
],
"flagWords": [],
Expand Down
76 changes: 55 additions & 21 deletions src/transformers/filter.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,70 @@
import { deferP0 } from "ts-functional-pipe";
import { toIterable } from "../helpers/toIterable";
import { IndexedPredicate } from "../types/IndexedPredicate";
import { TypeGuardPredicate } from "../types/TypeGuardPredicate";
import { _indexed } from "./indexed";

/**
* creates a new sequence with every item of the source sequence for which the predicate function returns `true`
* creates a new sequence with every item of the source sequence for which the predicate function
* returns a truthy/falsy value, optionally narrowing the type of the returned iterable (if a type-guard
* predicate is supplied)
*
* @remarks
* deferred version of {@link _filter}
*
* @param src source sequence
* @param pred a function that returns `true` to signal inclusion, `false` to exclude
* @returns a new (possibly shorter) sequence with some items filtered away
*
* @param pred a function that returns a truthy value to signal inclusion or a falsy value to exclude.
* Alternatively a type-guard function can be supplied
*
* @returns a new (possibly shorter) sequence with some items filtered away.
* If a type-guard (i.e. function returns something like `val is S`) is supplied for `pred`, then the
* resulting sequence will be narrowed to `Iterable<S>`
*/
export function _filter<T>(
src: Iterable<T>,
export function filter<T, S extends T>(
pred: TypeGuardPredicate<T, S>
): (src: Iterable<T>) => Iterable<S>;
export function filter<T>(
pred: IndexedPredicate<T>
): (src: Iterable<T>) => Iterable<T>;
export function filter<T>(
pred: IndexedPredicate<T>
): Iterable<T> {
return toIterable(function* () {
const s = _indexed(src);
for (const x of s) {
if (pred(...x)) {
yield x[0];
): (src: Iterable<T>) => Iterable<unknown> {
return (src: Iterable<T>): Iterable<unknown> =>
toIterable(function* () {
const indexedSrc = _indexed(src);
for (const v of indexedSrc) {
if (pred(...v)) {
yield v[0];
}
}
}
});
});
}

/**
* creates a new sequence with every item of the source sequence for which the predicate function returns `true`
*
* @remarks
* {@link https://biggyspender.github.io/ts-functional-pipe/globals.html#deferp0 P0 deferred} version of {@link _filter}
* creates a new sequence with every item of the source sequence for which the predicate function
* returns a truthy/falsy value, optionally narrowing the type of the returned iterable (if a type-guard
* predicate is supplied)
*
* @param src source sequence
* @param pred a function that returns `true` to signal inclusion, `false` to exclude
* @returns a new (possibly shorter) sequence with some items filtered away
*
* @param pred a function that returns a truthy value to signal inclusion or a falsy value to exclude.
* Alternatively a type-guard function can be supplied
*
* @returns a new (possibly shorter) sequence with some items filtered away.
* If a type-guard (i.e. function returns something like `val is S`) is supplied for `pred`, then the
* resulting sequence will be narrowed to `Iterable<S>`
*/
export const filter = deferP0(_filter);
export function _filter<T, S extends T>(
src: Iterable<T>,
pred: TypeGuardPredicate<T, S>
): Iterable<S>;
export function _filter<T>(
src: Iterable<T>,
pred: IndexedPredicate<T>
): Iterable<T>;
export function _filter<T>(
src: Iterable<T>,
pred: IndexedPredicate<T>
): Iterable<unknown> {
return filter(pred)(src);
}
4 changes: 2 additions & 2 deletions src/types/IndexedPredicate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Defines a predicate that takes a value `x:T` and number that represents the position of `x` in whichever sequence
* it is applied to and returns `true` or `false` usually to signal inclusion in an output list
* it is applied to and returns a truthy/falsy value, usually to signal inclusion in an output list
* @example {@link _filter}
*/

export type IndexedPredicate<T> = (x: T, i: number) => boolean;
export type IndexedPredicate<T> = (x: T, i: number) => unknown;
7 changes: 7 additions & 0 deletions src/types/TypeGuardPredicate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Defines a type-guard predicate that takes a value `x:T` and number that represents the position of `x` in whichever sequence
* and determines if the parameter `x` can be narrowed to type `S`
* @example {@link _filter}
*/

export type TypeGuardPredicate<T, S extends T> = (x: T, i: number) => x is S;

0 comments on commit f562868

Please sign in to comment.