From ec71a49e93621dfedc946b9259b0bc69fcde3b33 Mon Sep 17 00:00:00 2001 From: 4513ECHO Date: Tue, 20 Aug 2024 21:23:10 +0900 Subject: [PATCH 1/3] fix(filter): Support narrowing by type predicate --- async/filter.ts | 8 ++++++++ filter.ts | 8 ++++++++ pipe/async/filter.ts | 6 ++++++ pipe/filter.ts | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/async/filter.ts b/async/filter.ts index 51ae8db..2937c4c 100644 --- a/async/filter.ts +++ b/async/filter.ts @@ -1,3 +1,11 @@ +export function filter( + iterable: Iterable | AsyncIterable, + fn: (value: T, index: number) => boolean | Promise, +): AsyncIterable; +export function filter( + iterable: Iterable | AsyncIterable, + fn: (value: T, index: number) => value is U, +): AsyncIterable; /** * Filters an iterable based on a function. * diff --git a/filter.ts b/filter.ts index 05a4b8b..a6326a4 100644 --- a/filter.ts +++ b/filter.ts @@ -1,3 +1,11 @@ +export function filter( + iterable: Iterable, + fn: (value: T, index: number) => boolean, +): Iterable; +export function filter( + iterable: Iterable, + fn: (value: T, index: number) => value is U, +): Iterable; /** * Filters an iterable based on a function. * diff --git a/pipe/async/filter.ts b/pipe/async/filter.ts index be160af..0660d8d 100644 --- a/pipe/async/filter.ts +++ b/pipe/async/filter.ts @@ -1,5 +1,11 @@ import { filter as base } from "../../async/filter.ts"; +export function filter( + fn: (value: T, index: number) => boolean | Promise, +): (iterable: Iterable | AsyncIterable) => AsyncIterable; +export function filter( + fn: (value: T, index: number) => value is U, +): (iterable: Iterable | AsyncIterable) => AsyncIterable; /** * Returns an operator that filters an iterable based on a function. * diff --git a/pipe/filter.ts b/pipe/filter.ts index 065ded8..260471a 100644 --- a/pipe/filter.ts +++ b/pipe/filter.ts @@ -1,5 +1,11 @@ import { filter as base } from "../filter.ts"; +export function filter( + fn: (value: T, index: number) => boolean, +): (iterable: Iterable) => Iterable; +export function filter( + fn: (value: T, index: number) => value is U, +): (iterable: Iterable) => Iterable; /** * Returns an operator that filters an iterable based on a function. * From ed13790e7d926c1416aa65ae0cbae4b63ac53cda Mon Sep 17 00:00:00 2001 From: 4513ECHO Date: Tue, 20 Aug 2024 22:30:30 +0900 Subject: [PATCH 2/3] test: Add tests for filter with type predicate --- async/filter_test.ts | 8 ++++++++ filter_test.ts | 8 ++++++++ pipe/async/filter_test.ts | 11 +++++++++++ pipe/filter_test.ts | 11 +++++++++++ 4 files changed, 38 insertions(+) diff --git a/async/filter_test.ts b/async/filter_test.ts index 410fe42..4228c0e 100644 --- a/async/filter_test.ts +++ b/async/filter_test.ts @@ -69,3 +69,11 @@ await test("filter with iterable with promise", async () => { assertEquals(indices, [0, 1, 2, 3, 4]); assertType>>(true); }); + +await test("filter with type predicate", async () => { + const predicate = (v: number | string): v is number => typeof v === "number"; + const result = filter([1, "a", 2, "b", 3], predicate); + const expected = [1, 2, 3]; + assertEquals(await Array.fromAsync(result), expected); + assertType>>(true); +}); diff --git a/filter_test.ts b/filter_test.ts index e49c3e9..010047e 100644 --- a/filter_test.ts +++ b/filter_test.ts @@ -17,3 +17,11 @@ test("filter", () => { assertEquals(indices, [0, 1, 2, 3, 4]); assertType>>(true); }); + +test("filter with type predicate", () => { + const predicate = (v: number | string): v is number => typeof v === "number"; + const result = filter([1, "a", 2, "b", 3], predicate); + const expected = [1, 2, 3]; + assertEquals(Array.from(result), expected); + assertType>>(true); +}); diff --git a/pipe/async/filter_test.ts b/pipe/async/filter_test.ts index f327bf6..efcde95 100644 --- a/pipe/async/filter_test.ts +++ b/pipe/async/filter_test.ts @@ -13,3 +13,14 @@ test("filter usage", async () => { assertEquals(await Array.fromAsync(result), expected); assertType>>(true); }); + +test("filter usage with type predicate", async () => { + const predicate = (v: number | string): v is number => typeof v === "number"; + const result = pipe( + [1, "a", 2, "b", 3], + filter(predicate), + ); + const expected = [1, 2, 3]; + assertEquals(await Array.fromAsync(result), expected); + assertType>>(true); +}); diff --git a/pipe/filter_test.ts b/pipe/filter_test.ts index 04058ef..8f35fee 100644 --- a/pipe/filter_test.ts +++ b/pipe/filter_test.ts @@ -13,3 +13,14 @@ test("filter usage", () => { assertEquals(Array.from(result), expected); assertType>>(true); }); + +test("filter usage with type predicate", () => { + const predicate = (v: number | string): v is number => typeof v === "number"; + const result = pipe( + [1, "a", 2, "b", 3], + filter(predicate), + ); + const expected = [1, 2, 3]; + assertEquals(Array.from(result), expected); + assertType>>(true); +}); From 78d4eaf137ed1a67f1fe41a58040969e09a5d891 Mon Sep 17 00:00:00 2001 From: 4513ECHO Date: Tue, 20 Aug 2024 22:34:49 +0900 Subject: [PATCH 3/3] fix(filter): Sort overloads to correct order --- async/filter.ts | 8 ++++---- filter.ts | 8 ++++---- pipe/async/filter.ts | 6 +++--- pipe/filter.ts | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/async/filter.ts b/async/filter.ts index 2937c4c..c05af39 100644 --- a/async/filter.ts +++ b/async/filter.ts @@ -1,11 +1,11 @@ -export function filter( - iterable: Iterable | AsyncIterable, - fn: (value: T, index: number) => boolean | Promise, -): AsyncIterable; export function filter( iterable: Iterable | AsyncIterable, fn: (value: T, index: number) => value is U, ): AsyncIterable; +export function filter( + iterable: Iterable | AsyncIterable, + fn: (value: T, index: number) => boolean | Promise, +): AsyncIterable; /** * Filters an iterable based on a function. * diff --git a/filter.ts b/filter.ts index a6326a4..43f4459 100644 --- a/filter.ts +++ b/filter.ts @@ -1,11 +1,11 @@ -export function filter( - iterable: Iterable, - fn: (value: T, index: number) => boolean, -): Iterable; export function filter( iterable: Iterable, fn: (value: T, index: number) => value is U, ): Iterable; +export function filter( + iterable: Iterable, + fn: (value: T, index: number) => boolean, +): Iterable; /** * Filters an iterable based on a function. * diff --git a/pipe/async/filter.ts b/pipe/async/filter.ts index 0660d8d..b662c36 100644 --- a/pipe/async/filter.ts +++ b/pipe/async/filter.ts @@ -1,11 +1,11 @@ import { filter as base } from "../../async/filter.ts"; -export function filter( - fn: (value: T, index: number) => boolean | Promise, -): (iterable: Iterable | AsyncIterable) => AsyncIterable; export function filter( fn: (value: T, index: number) => value is U, ): (iterable: Iterable | AsyncIterable) => AsyncIterable; +export function filter( + fn: (value: T, index: number) => boolean | Promise, +): (iterable: Iterable | AsyncIterable) => AsyncIterable; /** * Returns an operator that filters an iterable based on a function. * diff --git a/pipe/filter.ts b/pipe/filter.ts index 260471a..1894819 100644 --- a/pipe/filter.ts +++ b/pipe/filter.ts @@ -1,11 +1,11 @@ import { filter as base } from "../filter.ts"; -export function filter( - fn: (value: T, index: number) => boolean, -): (iterable: Iterable) => Iterable; export function filter( fn: (value: T, index: number) => value is U, ): (iterable: Iterable) => Iterable; +export function filter( + fn: (value: T, index: number) => boolean, +): (iterable: Iterable) => Iterable; /** * Returns an operator that filters an iterable based on a function. *