diff --git a/fp_test.ts b/fp_test.ts index b2efdfc..b180dc5 100644 --- a/fp_test.ts +++ b/fp_test.ts @@ -1,4 +1,10 @@ -import { assertArrayIncludes, assertEquals } from "./test_deps.ts"; +import { + assertArrayIncludes, + assertEquals, + assertType, + type IsExact, +} from "./test_deps.ts"; + import { c, p } from "https://deno.land/x/copb@v1.0.1/mod.ts"; import * as mod from "./mod.ts"; import * as fp from "./fp.ts"; @@ -7,6 +13,14 @@ Deno.test("All functions are available in functional programming version", () => assertArrayIncludes(["curried", ...Object.keys(fp)], Object.keys(mod)); }); +Deno.test("Curried functions with type predicates type checks", () => { + const xs = [1, "a", 2, "b"]; + const result = fp.find((x): x is number => typeof x === "number")(xs); + + assertType>(true); + assertEquals(result, 1); +}); + Deno.test("With copb", () => { const pipeline = c( p(fp.map((x) => x * 100)) // Only needed type annotation, the rest is inferred. diff --git a/lib/reducers.ts b/lib/reducers.ts index 94fa128..bc75244 100644 --- a/lib/reducers.ts +++ b/lib/reducers.ts @@ -1,5 +1,8 @@ import { kComb } from "./internal/util.ts"; -import { IterablePredicateCallback } from "./types.ts"; +import { + IterablePredicateCallback, + IterableTypePredicateCallback, +} from "./types.ts"; import { map } from "./transformers.ts"; /** @@ -160,6 +163,15 @@ export function some( * // const allPositive = iter.every(naturals, (n) => n > 0); * ``` */ + +export function every( + it: Iterable, + predicate: IterablePredicateCallback, +): boolean; +export function every( + it: Iterable, + predicate: IterableTypePredicateCallback, +): it is Iterable; export function every( it: Iterable, predicate: IterablePredicateCallback, @@ -227,6 +239,14 @@ export function includes(it: Iterable, value: T): boolean { * // Find a solution to n³ = 3n, n ∈ ℕ * // const solution2 = iter.find(naturals, (n) => n ** 3 === 3 * n); */ +export function find( + it: Iterable, + predicate: IterablePredicateCallback, +): T | undefined; +export function find( + it: Iterable, + predicate: IterableTypePredicateCallback, +): S | undefined; export function find( it: Iterable, predicate: IterablePredicateCallback, diff --git a/lib/transformers.ts b/lib/transformers.ts index c48d09e..933c826 100644 --- a/lib/transformers.ts +++ b/lib/transformers.ts @@ -2,6 +2,7 @@ import { isIterable } from "./internal/util.ts"; import { IterableCircular, IterablePredicateCallback, + IterableTypePredicateCallback, Peekable, } from "./types.ts"; @@ -318,6 +319,14 @@ export function dropUntil( * // -> 5 * ``` */ +export function takeWhile( + it: Iterable, + f: IterablePredicateCallback, +): IterableCircular; +export function takeWhile( + it: Iterable, + f: IterableTypePredicateCallback, +): IterableCircular; export function takeWhile( it: Iterable, f: IterablePredicateCallback, @@ -354,6 +363,14 @@ export function takeWhile( * // -> 10 * ``` */ +export function dropWhile( + it: Iterable, + f: IterablePredicateCallback, +): IterableCircular; +export function dropWhile( + it: Iterable, + f: IterableTypePredicateCallback, +): IterableCircular; export function dropWhile( it: Iterable, f: IterablePredicateCallback, @@ -386,6 +403,14 @@ export function dropWhile( * console.log(iterator.next().value); // -> 11 * ``` */ +export function filter( + it: Iterable, + predicate: IterablePredicateCallback, +): IterableCircular; +export function filter( + it: Iterable, + predicate: IterableTypePredicateCallback, +): IterableCircular; export function filter( it: Iterable, predicate: IterablePredicateCallback, diff --git a/lib/types.ts b/lib/types.ts index 3416239..4d35c19 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -28,6 +28,23 @@ export interface IterablePredicateCallback { (value: T, index: number, it: Iterable): boolean; } +/** + * Iterable type predicate callback. + * @typeParam T - Type of value to be predicated. + * @typeParam S - Type of value to be narrowed to. + */ +export interface IterableTypePredicateCallback { + /** + * Iterable type predicate callback. + * @callback IterableTypePredicateCallback + * @param value - The value of the item being predicated. + * @param index - The index of the item being predicated. + * @param it - The iterable. + * @returns The narrowed predicate result. + */ + (value: T, index: number, it: Iterable): value is S; +} + /** * The same as the `Iterable` type, but the iterator implementation is iterable. * @typeParam T - Type of items in the iterable. diff --git a/test_deps.ts b/test_deps.ts index c3d25e5..b7dc03b 100644 --- a/test_deps.ts +++ b/test_deps.ts @@ -2,3 +2,7 @@ export { assert } from "https://deno.land/std@0.208.0/assert/assert.ts"; export { assertThrows } from "https://deno.land/std@0.208.0/assert/assert_throws.ts"; export { assertEquals } from "https://deno.land/std@0.208.0/assert/assert_equals.ts"; export { assertArrayIncludes } from "https://deno.land/std@0.208.0/assert/assert_array_includes.ts"; +export { + assertType, + type IsExact, +} from "https://deno.land/std@0.209.0/testing/types.ts";