Skip to content

Commit

Permalink
Merge pull request #2 from jsr-core/allow-malformed-iterator-on-chain
Browse files Browse the repository at this point in the history
feat: support chaining malformed iterables
  • Loading branch information
lambdalisue authored Aug 8, 2024
2 parents 2f5ea63 + 15d7c3e commit 4a4d1bb
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 11 deletions.
28 changes: 24 additions & 4 deletions async/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,33 @@
* const iter = chain([1, 2], [3, 4]);
* console.log(await toArray(iter)); // [1, 2, 3, 4]
* ```
*
* It supports chaining malformed iterables.
*
* @example
* ```ts
* import { toArray } from "@core/iterutil/async/to-array";
* import { chain } from "@core/iterutil/async/chain";
*
* const iter = chain([1, 2], ["a", "b"], [true]);
* console.log(await toArray(iter)); // [1, 2, "a", "b", true]
* ```
*/
export async function* chain<T>(
...iterables: (Iterable<T> | AsyncIterable<T>)[]
): AsyncIterable<T> {
export async function* chain<
T extends (Iterable<unknown> | AsyncIterable<unknown>)[],
>(
...iterables: T
): AsyncIterable<Chain<T>> {
for await (const iterable of iterables) {
for await (const value of iterable) {
yield value;
yield value as Chain<T>;
}
}
}

export type Chain<T> = T extends readonly [] ? never
: T extends readonly [Iterable<infer U>] ? U
: T extends readonly [AsyncIterable<infer U>] ? U
: T extends readonly [Iterable<infer U>, ...infer R] ? U | Chain<R>
: T extends readonly [AsyncIterable<infer U>, ...infer R] ? U | Chain<R>
: never;
13 changes: 13 additions & 0 deletions async/chain_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,17 @@ Deno.test("chain", async (t) => {
assertEquals(await toArray(result), expected);
assertType<IsExact<typeof result, AsyncIterable<number>>>(true);
});

await t.step("with malform iterable", async () => {
const result = chain(
toAsyncIterable([1, 2]),
["a", "b"],
toAsyncIterable([true]),
);
const expected = [1, 2, "a", "b", true];
assertEquals(await toArray(result), expected);
assertType<
IsExact<typeof result, AsyncIterable<number | string | boolean>>
>(true);
});
});
21 changes: 19 additions & 2 deletions chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,26 @@
* const iter = chain([1, 2], [3, 4]);
* console.log([...iter]); // [1, 2, 3, 4]
* ```
*
* It supports chaining malformed iterables.
*
* @example
* ```ts
* import { chain } from "@core/iterutil/chain";
*
* const iter = chain([1, 2], ["a", "b"], [true]);
* console.log([...iter]); // [1, 2, "a", "b", true]
* ```
*/
export function* chain<T>(...iterables: Iterable<T>[]): Iterable<T> {
export function* chain<T extends Iterable<unknown>[]>(
...iterables: T
): Iterable<Chain<T>> {
for (const iterable of iterables) {
yield* iterable;
yield* iterable as Iterable<Chain<T>>;
}
}

export type Chain<T> = T extends readonly [] ? never
: T extends readonly [Iterable<infer U>] ? U
: T extends readonly [Iterable<infer U>, ...infer R] ? U | Chain<R>
: never;
21 changes: 16 additions & 5 deletions chain_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@ import { assertEquals } from "@std/assert";
import { assertType, type IsExact } from "@std/testing/types";
import { chain } from "./chain.ts";

Deno.test("chain", () => {
const result = chain([1, 2], [3, 4], [5]);
const expected = [1, 2, 3, 4, 5];
assertEquals([...result], expected);
assertType<IsExact<typeof result, Iterable<number>>>(true);
Deno.test("chain", async (t) => {
await t.step("uniform iterables", () => {
const result = chain([1, 2], [3, 4], [5]);
const expected = [1, 2, 3, 4, 5];
assertEquals([...result], expected);
assertType<IsExact<typeof result, Iterable<number>>>(true);
});

await t.step("malform iterables", () => {
const result = chain([1, 2], ["a", "b"], [true]);
const expected = [1, 2, "a", "b", true];
assertEquals([...result], expected);
assertType<IsExact<typeof result, Iterable<number | string | boolean>>>(
true,
);
});
});

0 comments on commit 4a4d1bb

Please sign in to comment.