We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
2 parents 2f5ea63 + 15d7c3e commit 4a4d1bbCopy full SHA for 4a4d1bb
async/chain.ts
@@ -12,13 +12,33 @@
12
* const iter = chain([1, 2], [3, 4]);
13
* console.log(await toArray(iter)); // [1, 2, 3, 4]
14
* ```
15
+ *
16
+ * It supports chaining malformed iterables.
17
18
+ * @example
19
+ * ```ts
20
+ * import { toArray } from "@core/iterutil/async/to-array";
21
+ * import { chain } from "@core/iterutil/async/chain";
22
23
+ * const iter = chain([1, 2], ["a", "b"], [true]);
24
+ * console.log(await toArray(iter)); // [1, 2, "a", "b", true]
25
+ * ```
26
*/
-export async function* chain<T>(
- ...iterables: (Iterable<T> | AsyncIterable<T>)[]
-): AsyncIterable<T> {
27
+export async function* chain<
28
+ T extends (Iterable<unknown> | AsyncIterable<unknown>)[],
29
+>(
30
+ ...iterables: T
31
+): AsyncIterable<Chain<T>> {
32
for await (const iterable of iterables) {
33
for await (const value of iterable) {
- yield value;
34
+ yield value as Chain<T>;
35
}
36
37
38
+
39
+export type Chain<T> = T extends readonly [] ? never
40
+ : T extends readonly [Iterable<infer U>] ? U
41
+ : T extends readonly [AsyncIterable<infer U>] ? U
42
+ : T extends readonly [Iterable<infer U>, ...infer R] ? U | Chain<R>
43
+ : T extends readonly [AsyncIterable<infer U>, ...infer R] ? U | Chain<R>
44
+ : never;
async/chain_test.ts
@@ -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);
45
+ assertType<
46
+ IsExact<typeof result, AsyncIterable<number | string | boolean>>
47
+ >(true);
48
+ });
49
chain.ts
@@ -11,9 +11,26 @@
11
* console.log([...iter]); // [1, 2, 3, 4]
+ * import { chain } from "@core/iterutil/chain";
+ * console.log([...iter]); // [1, 2, "a", "b", true]
-export function* chain<T>(...iterables: Iterable<T>[]): Iterable<T> {
+export function* chain<T extends Iterable<unknown>[]>(
+): Iterable<Chain<T>> {
for (const iterable of iterables) {
- yield* iterable;
+ yield* iterable as Iterable<Chain<T>>;
chain_test.ts
@@ -2,9 +2,20 @@ import { assertEquals } from "@std/assert";
2
import { assertType, type IsExact } from "@std/testing/types";
3
import { chain } from "./chain.ts";
4
5
-Deno.test("chain", () => {
6
- const result = chain([1, 2], [3, 4], [5]);
7
- const expected = [1, 2, 3, 4, 5];
8
- assertEquals([...result], expected);
9
- 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);
10
+ assertType<IsExact<typeof result, Iterable<number>>>(true);
+ await t.step("malform iterables", () => {
+ const result = chain([1, 2], ["a", "b"], [true]);
+ assertType<IsExact<typeof result, Iterable<number | string | boolean>>>(
+ true,
0 commit comments