Skip to content

Commit

Permalink
feat: use better typing for .find() (#1)
Browse files Browse the repository at this point in the history
* feat: use better typing for .find()

* test: improve test coverage

* ci: add explicit run for v1.16

* test: refactor
  • Loading branch information
LumaKernel authored Dec 15, 2021
1 parent 5ef5a71 commit 730f9f5
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 81 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
deno: v1.10
- os: ubuntu-latest
deno: v1.13
- os: ubuntu-latest
deno: v1.16
- os: ubuntu-latest
deno: canary
- os: windows-latest
Expand Down
11 changes: 9 additions & 2 deletions lib/wrap_async_iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ export type WrappedAsyncIterator<T> = {
forEach: (fn: (t: T) => void | Promise<void>) => Promise<void>;
some: (fn: (t: T) => boolean | Promise<boolean>) => Promise<boolean>;
every: (fn: (t: T) => boolean | Promise<boolean>) => Promise<boolean>;
find: (fn: (t: T) => boolean | Promise<boolean>) => Promise<T | undefined>;
find: {
<U extends T>(
filtererFn: (t: T) => t is U,
): Promise<U | undefined>;
(
filtererFn: (t: T) => boolean | Promise<boolean>,
): Promise<T | undefined>;
};
};

export const wrapAsyncIterator = <T>(
Expand Down Expand Up @@ -186,7 +193,7 @@ export const wrapAsyncIterator = <T>(
}
return true;
},
find: async (fn) => {
find: async (fn: any) => {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
Expand Down
11 changes: 9 additions & 2 deletions lib/wrap_iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ export type WrappedIterator<T> = {
forEach: (fn: (t: T) => void) => void;
some: (fn: (t: T) => boolean) => boolean;
every: (fn: (t: T) => boolean) => boolean;
find: (fn: (t: T) => boolean) => T | undefined;
find: {
<U extends T>(
filtererFn: (t: T) => t is U,
): U | undefined;
(
filtererFn: (t: T) => boolean,
): T | undefined;
};
};

export const wrapIterator = <T>(ite: Iterator<T>): WrappedIterator<T> => {
Expand Down Expand Up @@ -169,7 +176,7 @@ export const wrapIterator = <T>(ite: Iterator<T>): WrappedIterator<T> => {
}
return true;
},
find: (fn) => {
find: (fn: any) => {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
Expand Down
78 changes: 39 additions & 39 deletions test/unit/wrap_async_iterator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ import { asserts } from "../../deps.ts";
import { wrapAsyncIterator } from "../../lib/wrap_async_iterator.ts";
import { asyncIteratorFrom } from "../../lib/async_iterator_from.ts";

const naturals = async function* naturals() {
let i = 0;
while (true) {
await Promise.resolve();
yield i;
i += 1;
}
};

type Prime10 = 2 | 3 | 5 | 7;
const isPrime10 = (n: number): n is Prime10 =>
n === 2 || n === 3 || n === 5 || n === 7;

Deno.test({
name: "AsyncIterator.prototype.map",
async fn() {
const naturals = async function* naturals() {
let i = 0;
while (true) {
await Promise.resolve();
yield i;
i += 1;
}
};
const naturalsStr: AsyncIterator<string> = wrapAsyncIterator(naturals())
.map((e) => e.toString())
.unwrap();
Expand All @@ -32,16 +37,7 @@ Deno.test({
Deno.test({
name: "AsyncIterator.prototype.filter",
async fn() {
const naturals = async function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
const isPrime10 = (n: number): n is 2 | 3 | 5 | 7 =>
n === 2 || n === 3 || n === 5 || n === 7;
const prime10: AsyncIterator<2 | 3 | 5 | 7> = wrapAsyncIterator(naturals())
const prime10: AsyncIterator<Prime10> = wrapAsyncIterator(naturals())
.filter(isPrime10)
.unwrap();
asserts.assertEquals(
Expand All @@ -58,13 +54,6 @@ Deno.test({
Deno.test({
name: "AsyncIterator.prototype.take",
async fn() {
const naturals = async function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
await wrapAsyncIterator(naturals()).take(4).toArray(),
[0, 1, 2, 3],
Expand Down Expand Up @@ -117,13 +106,6 @@ Deno.test({
name: "AsyncIterator.prototype.drop",
async fn() {
{
const naturals = async function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
await wrapAsyncIterator(naturals()).drop(4).take(4).toArray(),
[4, 5, 6, 7],
Expand Down Expand Up @@ -192,13 +174,6 @@ Deno.test({
Deno.test({
name: "AsyncIterator.prototype.asIndexedPairs",
async fn() {
const naturals = async function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
await wrapAsyncIterator(naturals())
.filter((e) => e % 2 === 1)
Expand All @@ -225,6 +200,31 @@ Deno.test({
.toArray(),
[100, 200, 3, 4, 5, [6, 7], 8, 9, 10, 11],
);
asserts.assertEquals(
await wrapAsyncIterator(asyncIteratorFrom([
1,
]))
.flatMap<number | number[]>(async function* (e) {
yield e * 10;
yield e * 20;
})
.toArray(),
[10, 20],
);
await asserts.assertRejects(
async () =>
await wrapAsyncIterator(asyncIteratorFrom([0])).flatMap(() => ({
[Symbol.asyncIterator]: 0,
})).toArray(),
TypeError,
);
await asserts.assertRejects(
async () =>
await wrapAsyncIterator(asyncIteratorFrom([0])).flatMap(() => ({
[Symbol.iterator]: 0,
})).toArray(),
TypeError,
);
asserts.assertThrows(
() => wrapAsyncIterator(asyncIteratorFrom([1, 2, 3])).flatMap(1 as any),
TypeError,
Expand Down
75 changes: 37 additions & 38 deletions test/unit/wrap_iterator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ import { asserts } from "../../deps.ts";
import { iteratorFrom } from "../../lib/iterator_from.ts";
import { wrapIterator } from "../../lib/wrap_iterator.ts";

const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};

type Prime10 = 2 | 3 | 5 | 7;
const isPrime10 = (n: number): n is Prime10 =>
n === 2 || n === 3 || n === 5 || n === 7;

Deno.test({
name: "Iterator.prototype.map",
fn() {
const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
const naturalsStr: Iterator<string> = wrapIterator(naturals())
.map((e) => e.toString())
.unwrap();
Expand All @@ -31,16 +36,7 @@ Deno.test({
Deno.test({
name: "Iterator.prototype.filter",
fn() {
const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
const isPrime10 = (n: number): n is 2 | 3 | 5 | 7 =>
n === 2 || n === 3 || n === 5 || n === 7;
const prime10: Iterator<2 | 3 | 5 | 7> = wrapIterator(naturals())
const prime10: Iterator<Prime10> = wrapIterator(naturals())
.filter(isPrime10)
.unwrap();
asserts.assertEquals(
Expand All @@ -57,13 +53,6 @@ Deno.test({
Deno.test({
name: "Iterator.prototype.take",
fn() {
const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
wrapIterator(naturals()).take(4).toArray(),
[0, 1, 2, 3],
Expand Down Expand Up @@ -115,13 +104,6 @@ Deno.test({
name: "Iterator.prototype.drop",
fn() {
{
const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
wrapIterator(naturals()).drop(4).take(4).toArray(),
[4, 5, 6, 7],
Expand Down Expand Up @@ -190,13 +172,6 @@ Deno.test({
Deno.test({
name: "Iterator.prototype.asIndexedPairs",
fn() {
const naturals = function* naturals() {
let i = 0;
while (true) {
yield i;
i += 1;
}
};
asserts.assertEquals(
wrapIterator(naturals())
.filter((e) => e % 2 === 1)
Expand All @@ -223,6 +198,24 @@ Deno.test({
.toArray(),
[100, 200, 3, 4, 5, [6, 7], 8, 9, 10, 11],
);
asserts.assertEquals(
wrapIterator(iteratorFrom([
1,
]))
.flatMap<number | number[]>(function* (e) {
yield e * 10;
yield e * 20;
})
.toArray(),
[10, 20],
);
asserts.assertThrows(
() =>
wrapIterator(iteratorFrom([0])).flatMap(() => ({
[Symbol.iterator]: 0,
})).toArray(),
TypeError,
);
asserts.assertThrows(
() => wrapIterator(iteratorFrom([1, 2, 3])).flatMap(1 as any),
TypeError,
Expand Down Expand Up @@ -386,6 +379,12 @@ Deno.test({
TypeError,
);
}
{
const got: Prime10 | undefined = wrapIterator(naturals())
.take(10)
.find(isPrime10);
asserts.assertEquals(got, 2);
}
{
asserts.assertEquals(
wrapIterator(
Expand Down

0 comments on commit 730f9f5

Please sign in to comment.