Skip to content

Commit 66551b7

Browse files
authored
Merge pull request #7 from jsr-core/compose
feat: Add `compose` function for composing multiple operators
2 parents fdee976 + 2936dc6 commit 66551b7

17 files changed

+2294
-978
lines changed

.github/FUNDING.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# These are supported funding model platforms
22

3-
github: [lambdalisue] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
3+
github: [
4+
lambdalisue,
5+
] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
46
patreon: # Replace with a single Patreon username
57
open_collective: # Replace with a single Open Collective username
68
ko_fi: # Replace with a single Ko-fi username

README.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inference and type checking of the operator functions.
2121
Pipe a value through a series of operator functions.
2222

2323
```ts
24-
import { pipe } from "@core/pipe";
24+
import { pipe } from "@core/pipe/pipe";
2525

2626
const result = pipe(
2727
1,
@@ -36,7 +36,7 @@ Or use `async` module to pipe a value through a series of asynchronous operator
3636
functions.
3737

3838
```ts
39-
import { pipe } from "@core/pipe/async";
39+
import { pipe } from "@core/pipe/async/pipe";
4040

4141
const result = await pipe(
4242
1,
@@ -47,6 +47,65 @@ const result = await pipe(
4747
console.log(result); // "4"
4848
```
4949

50+
If you want to create a new function that composes multiple operators, use
51+
`compose` like below.
52+
53+
```ts
54+
import { compose } from "@core/pipe/compose";
55+
56+
const operator = compose(
57+
(v: number) => v + 1, // The first operator must be typed explicitly
58+
(v) => v * 2, // inferred as (v: number) => number
59+
(v) => v.toString(), // inferred as (v: number) => string
60+
);
61+
console.log(operator(1)); // "4"
62+
```
63+
64+
Or use `async` module to compose multiple asynchronous operators.
65+
66+
```ts
67+
import { compose } from "@core/pipe/async/compose";
68+
69+
const operator = compose(
70+
(v: number) => Promise.resolve(v + 1), // The first operator must be typed explicitly
71+
(v) => Promise.resolve(v * 2), // inferred as (v: number) => number | Promise<number>
72+
(v) => Promise.resolve(v.toString()), // inferred as (v: number) => string | Promise<string>
73+
);
74+
console.log(await operator(1)); // "4"
75+
```
76+
77+
## Difference
78+
79+
The `pipe` function in the root module is equivalent to function calls without
80+
`await` like below.
81+
82+
```ts
83+
import { pipe } from "@core/pipe/pipe";
84+
85+
const a = (v: unknown) => v;
86+
const b = (v: unknown) => v;
87+
const c = (v: unknown) => v;
88+
89+
// Equivalent
90+
console.log(pipe(1, a, b, c)); // 1
91+
console.log(c(b(a(1)))); // 1
92+
```
93+
94+
The `pipe` function in the `async` module is equivalent to function calls with
95+
`await` like below.
96+
97+
```ts
98+
import { pipe } from "@core/pipe/async/pipe";
99+
100+
const a = (v: unknown) => Promise.resolve(v);
101+
const b = (v: unknown) => Promise.resolve(v);
102+
const c = (v: unknown) => Promise.resolve(v);
103+
104+
// Equivalent
105+
console.log(await pipe(1, a, b, c)); // 1
106+
console.log(await c(await b(await a(1)))); // 1
107+
```
108+
50109
## License
51110

52111
The code follows MIT license written in [LICENSE](./LICENSE). Contributors need

_common.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { Operator } from "./operator.ts";
2+
3+
/**
4+
* @internal
5+
*/
6+
export type LastOperatorReturn<T extends Operator<unknown, unknown>[]> =
7+
T extends [...Operator<unknown, unknown>[], Operator<unknown, infer R>] ? R
8+
: never;

async/_common.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { AsyncOperator } from "./operator.ts";
2+
3+
/**
4+
* @internal
5+
*/
6+
export type LastAsyncOperatorReturn<
7+
T extends AsyncOperator<unknown, unknown>[],
8+
> = T extends
9+
[...AsyncOperator<unknown, unknown>[], AsyncOperator<unknown, infer R>] ? R
10+
: never;

0 commit comments

Comments
 (0)