Skip to content

Commit 2cf67f5

Browse files
authored
Merge pull request #21 from 4513ECHO/filter-overload
fix(filter): Support narrowing by type predicate
2 parents 85fd83b + 78d4eaf commit 2cf67f5

File tree

8 files changed

+66
-0
lines changed

8 files changed

+66
-0
lines changed

async/filter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
export function filter<T, U extends T>(
2+
iterable: Iterable<T> | AsyncIterable<T>,
3+
fn: (value: T, index: number) => value is U,
4+
): AsyncIterable<U>;
5+
export function filter<T>(
6+
iterable: Iterable<T> | AsyncIterable<T>,
7+
fn: (value: T, index: number) => boolean | Promise<boolean>,
8+
): AsyncIterable<T>;
19
/**
210
* Filters an iterable based on a function.
311
*

async/filter_test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,11 @@ await test("filter with iterable with promise", async () => {
6969
assertEquals(indices, [0, 1, 2, 3, 4]);
7070
assertType<IsExact<typeof result, AsyncIterable<number>>>(true);
7171
});
72+
73+
await test("filter with type predicate", async () => {
74+
const predicate = (v: number | string): v is number => typeof v === "number";
75+
const result = filter([1, "a", 2, "b", 3], predicate);
76+
const expected = [1, 2, 3];
77+
assertEquals(await Array.fromAsync(result), expected);
78+
assertType<IsExact<typeof result, AsyncIterable<number>>>(true);
79+
});

filter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
export function filter<T, U extends T>(
2+
iterable: Iterable<T>,
3+
fn: (value: T, index: number) => value is U,
4+
): Iterable<U>;
5+
export function filter<T>(
6+
iterable: Iterable<T>,
7+
fn: (value: T, index: number) => boolean,
8+
): Iterable<T>;
19
/**
210
* Filters an iterable based on a function.
311
*

filter_test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ test("filter", () => {
1717
assertEquals(indices, [0, 1, 2, 3, 4]);
1818
assertType<IsExact<typeof result, Iterable<number>>>(true);
1919
});
20+
21+
test("filter with type predicate", () => {
22+
const predicate = (v: number | string): v is number => typeof v === "number";
23+
const result = filter([1, "a", 2, "b", 3], predicate);
24+
const expected = [1, 2, 3];
25+
assertEquals(Array.from(result), expected);
26+
assertType<IsExact<typeof result, Iterable<number>>>(true);
27+
});

pipe/async/filter.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { filter as base } from "../../async/filter.ts";
22

3+
export function filter<T, U extends T>(
4+
fn: (value: T, index: number) => value is U,
5+
): (iterable: Iterable<T> | AsyncIterable<T>) => AsyncIterable<U>;
6+
export function filter<T>(
7+
fn: (value: T, index: number) => boolean | Promise<boolean>,
8+
): (iterable: Iterable<T> | AsyncIterable<T>) => AsyncIterable<T>;
39
/**
410
* Returns an operator that filters an iterable based on a function.
511
*

pipe/async/filter_test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,14 @@ test("filter usage", async () => {
1313
assertEquals(await Array.fromAsync(result), expected);
1414
assertType<IsExact<typeof result, AsyncIterable<number>>>(true);
1515
});
16+
17+
test("filter usage with type predicate", async () => {
18+
const predicate = (v: number | string): v is number => typeof v === "number";
19+
const result = pipe(
20+
[1, "a", 2, "b", 3],
21+
filter(predicate),
22+
);
23+
const expected = [1, 2, 3];
24+
assertEquals(await Array.fromAsync(result), expected);
25+
assertType<IsExact<typeof result, AsyncIterable<number>>>(true);
26+
});

pipe/filter.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { filter as base } from "../filter.ts";
22

3+
export function filter<T, U extends T>(
4+
fn: (value: T, index: number) => value is U,
5+
): (iterable: Iterable<T>) => Iterable<U>;
6+
export function filter<T>(
7+
fn: (value: T, index: number) => boolean,
8+
): (iterable: Iterable<T>) => Iterable<T>;
39
/**
410
* Returns an operator that filters an iterable based on a function.
511
*

pipe/filter_test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,14 @@ test("filter usage", () => {
1313
assertEquals(Array.from(result), expected);
1414
assertType<IsExact<typeof result, Iterable<number>>>(true);
1515
});
16+
17+
test("filter usage with type predicate", () => {
18+
const predicate = (v: number | string): v is number => typeof v === "number";
19+
const result = pipe(
20+
[1, "a", 2, "b", 3],
21+
filter(predicate),
22+
);
23+
const expected = [1, 2, 3];
24+
assertEquals(Array.from(result), expected);
25+
assertType<IsExact<typeof result, Iterable<number>>>(true);
26+
});

0 commit comments

Comments
 (0)