kind-adt 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -1
- package/index.d.ts +152 -67
- package/index.js +54 -11
- package/package.json +1 -1
- package/utils.d.ts +0 -2
- package/utils.js +7 -19
package/README.md
CHANGED
|
@@ -48,13 +48,14 @@ function safeDivide(n: number, d: number) {
|
|
|
48
48
|
match(safeDivide(42, 2), {
|
|
49
49
|
Some: (n) => console.log("Result:", n),
|
|
50
50
|
None: () => console.log("Division by zero!"),
|
|
51
|
-
})
|
|
51
|
+
});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
## Features
|
|
55
55
|
|
|
56
56
|
- _One_ type to define your **A**lgebraic **D**ata **T**ype (`Data`).
|
|
57
57
|
- _One_ function to create **constructors**, **deconstructors**, **type guards** and **pattern matching function** for your ADT with **type safety** (`make`).
|
|
58
|
+
- Support for **functional pipelines** with a [`.pipe()` method](#functional-pipelines-with-pipe) on all ADTs.
|
|
58
59
|
- [**Readable type signatures**](#provide-more-readable-type-signatures) for your ADT with _labeled tuples_.
|
|
59
60
|
- [**Recursive ADTs**](#recursive-adts) with ease.
|
|
60
61
|
- Tiny footprint (~1kB minzipped).
|
|
@@ -197,6 +198,8 @@ pipe(
|
|
|
197
198
|
); // => 84
|
|
198
199
|
```
|
|
199
200
|
|
|
201
|
+
See also the [functional pipelines with `.pipe()`](#functional-pipelines-with-pipe) section for details on kind-adt’s built-in alternative to external pipe utilities.
|
|
202
|
+
|
|
200
203
|
Note that `ADT.match` requires the return type of each case to be the same. To allow different return types, you can use the `ADT.matchW` function, where the `W` suffix stands for _wider_. `ADT.matchW` can be used the same way as `ADT.match`, supporting both curried and non-curried overloads.
|
|
201
204
|
|
|
202
205
|
<div align="right">
|
|
@@ -250,6 +253,60 @@ type None = Extract<Option<unknown>, Tagged<"None">>;
|
|
|
250
253
|
// }
|
|
251
254
|
```
|
|
252
255
|
|
|
256
|
+
### Functional pipelines with `.pipe()`
|
|
257
|
+
|
|
258
|
+
Every ADT in kind-adt supports a `.pipe()` method, allowing for a more functional and fluent style of programming similar to libraries like [Effect](https://github.com/Effect-TS/effect) or [RxJS](https://rxjs.dev/api/index/function/pipe).
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { type Data, make } from "kind-adt";
|
|
262
|
+
import type { Arg0, HKT } from "hkt-core";
|
|
263
|
+
|
|
264
|
+
type Option<T> = Data<{
|
|
265
|
+
Some: [value: T];
|
|
266
|
+
None: [];
|
|
267
|
+
}>;
|
|
268
|
+
|
|
269
|
+
const { Some, None, match } = make<OptionHKT>();
|
|
270
|
+
interface OptionHKT extends HKT {
|
|
271
|
+
return: Option<Arg0<this>>;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const map: <T, R>(fn: (value: T) => R) => (opt: Option<T>) => Option<R> = (fn) =>
|
|
275
|
+
match({
|
|
276
|
+
Some: (value) => Some(fn(value)),
|
|
277
|
+
None: () => None,
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Using pipe with an ADT
|
|
281
|
+
Some(42).pipe(
|
|
282
|
+
map((n) => n + 1),
|
|
283
|
+
map((n) => n * 2),
|
|
284
|
+
match({
|
|
285
|
+
Some: (n) => console.log("Result:", n),
|
|
286
|
+
None: () => console.log("No value"),
|
|
287
|
+
}),
|
|
288
|
+
);
|
|
289
|
+
//> Result: 86
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Under the hood, any value returned by a constructor already has a `.pipe()` method, which takes a sequence of functions and applies them one after another, with each function receiving the result of the previous function.
|
|
293
|
+
|
|
294
|
+
You can also create your own objects with the same `.pipe()` functionality using the exported `Pipeable` interface and `PipeableProto`:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { type Pipeable, PipeableProto } from "kind-adt";
|
|
298
|
+
|
|
299
|
+
// Create a pipeable object
|
|
300
|
+
const myData = Object.create(PipeableProto);
|
|
301
|
+
myData.value = 42;
|
|
302
|
+
|
|
303
|
+
// Use the pipe method
|
|
304
|
+
const result = myData.pipe(
|
|
305
|
+
(obj) => obj.value * 2,
|
|
306
|
+
(n) => n.toString(),
|
|
307
|
+
); // => "84"
|
|
308
|
+
```
|
|
309
|
+
|
|
253
310
|
### Provide more readable type signatures
|
|
254
311
|
|
|
255
312
|
Let’s revisit the `Option<T>` example in the quickstart section.
|
package/index.d.ts
CHANGED
|
@@ -54,6 +54,84 @@ export function make<F extends Tagged | TypeLambda<never, Tagged>>(
|
|
|
54
54
|
*/
|
|
55
55
|
export function unwrap<T extends Tagged>(adt: T): ExtractFields<T>;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* A type that supports an [RxJS](https://rxjs.dev/api/index/function/pipe)-like
|
|
59
|
+
* (or [Effect](https://github.com/Effect-TS/effect)-like) `.pipe()` method.
|
|
60
|
+
*/
|
|
61
|
+
export interface Pipeable {
|
|
62
|
+
/**
|
|
63
|
+
* Pipe the value through a series of functions.
|
|
64
|
+
*
|
|
65
|
+
* **Example**
|
|
66
|
+
*
|
|
67
|
+
* ```typescript
|
|
68
|
+
* import { type Data, make } from "kind-adt";
|
|
69
|
+
*
|
|
70
|
+
* type BoxNumber = Data<{
|
|
71
|
+
* Box: [number];
|
|
72
|
+
* }>;
|
|
73
|
+
* const { Box } = make<BoxNumber>();
|
|
74
|
+
*
|
|
75
|
+
* Box(42).pipe((box) => box._0 + 1, (n) => n * 2, (n) => n.toString()); // => "86"
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
pipe<A>(this: A): A;
|
|
79
|
+
pipe<A, B = never>(this: A, ab: (a: A) => B): B;
|
|
80
|
+
// prettier-ignore
|
|
81
|
+
pipe<A, B = never, C = never>(this: A, ab: (a: A) => B, bc: (b: B) => C): C;
|
|
82
|
+
// prettier-ignore
|
|
83
|
+
pipe<A, B = never, C = never, D = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;
|
|
84
|
+
// prettier-ignore
|
|
85
|
+
pipe<A, B = never, C = never, D = never, E = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E): E;
|
|
86
|
+
// prettier-ignore
|
|
87
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F): F;
|
|
88
|
+
// prettier-ignore
|
|
89
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G): G;
|
|
90
|
+
// prettier-ignore
|
|
91
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H): H;
|
|
92
|
+
// prettier-ignore
|
|
93
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I): I;
|
|
94
|
+
// prettier-ignore
|
|
95
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J): J;
|
|
96
|
+
// prettier-ignore
|
|
97
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K): K;
|
|
98
|
+
// prettier-ignore
|
|
99
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L): L;
|
|
100
|
+
// prettier-ignore
|
|
101
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M): M;
|
|
102
|
+
// prettier-ignore
|
|
103
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N): N;
|
|
104
|
+
// prettier-ignore
|
|
105
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O): O;
|
|
106
|
+
// prettier-ignore
|
|
107
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P): P;
|
|
108
|
+
// prettier-ignore
|
|
109
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q): Q;
|
|
110
|
+
// prettier-ignore
|
|
111
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R): R;
|
|
112
|
+
// prettier-ignore
|
|
113
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S): S;
|
|
114
|
+
// prettier-ignore
|
|
115
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T): T;
|
|
116
|
+
// prettier-ignore
|
|
117
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U): U;
|
|
118
|
+
// prettier-ignore
|
|
119
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never, V = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U, uv: (u: U) => V): V;
|
|
120
|
+
// prettier-ignore
|
|
121
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never, V = never, W = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U, uv: (u: U) => V, vw: (v: V) => W): W;
|
|
122
|
+
// prettier-ignore
|
|
123
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never, V = never, W = never, X = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U, uv: (u: U) => V, vw: (v: V) => W, wx: (w: W) => X): X;
|
|
124
|
+
// prettier-ignore
|
|
125
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never, V = never, W = never, X = never, Y = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U, uv: (u: U) => V, vw: (v: V) => W, wx: (w: W) => X, xy: (x: X) => Y): Y;
|
|
126
|
+
// prettier-ignore
|
|
127
|
+
pipe<A, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never, K = never, L = never, M = never, N = never, O = never, P = never, Q = never, R = never, S = never, T = never, U = never, V = never, W = never, X = never, Y = never, Z = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T, tu: (t: T) => U, uv: (u: U) => V, vw: (v: V) => W, wx: (w: W) => X, xy: (x: X) => Y, yz: (y: Y) => Z): Z;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The prototype to build a {@linkcode Pipeable} object.
|
|
132
|
+
*/
|
|
133
|
+
export const PipeableProto: Pipeable;
|
|
134
|
+
|
|
57
135
|
/**************
|
|
58
136
|
* Main types *
|
|
59
137
|
**************/
|
|
@@ -93,7 +171,8 @@ export type Tagged<
|
|
|
93
171
|
) extends infer Fields ?
|
|
94
172
|
{ readonly [I in IndexOf<Fields> as `_${I}`]: Fields[I] }
|
|
95
173
|
: never
|
|
96
|
-
|
|
174
|
+
> &
|
|
175
|
+
Pipeable;
|
|
97
176
|
|
|
98
177
|
/**
|
|
99
178
|
* Create an ADT with tagged types.
|
|
@@ -303,89 +382,92 @@ export type Constructor<
|
|
|
303
382
|
[Type] extends (
|
|
304
383
|
[Tagged] // Non-generic ADT
|
|
305
384
|
) ?
|
|
306
|
-
{ readonly _tag: Tag } &
|
|
307
|
-
...args: ExtractFields<Extract<Type, Tagged<Tag>>>
|
|
308
|
-
) => Type)
|
|
385
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
386
|
+
((...args: ExtractFields<Extract<Type, Tagged<Tag>>>) => Type)
|
|
309
387
|
: // Generic ADT
|
|
310
388
|
Type extends TypeLambda<[never], unknown> ?
|
|
311
389
|
unknown extends _UpperBound<HKTParams<Type>[0]> ?
|
|
312
|
-
{ readonly _tag: Tag } &
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
390
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
391
|
+
(<T = never>(
|
|
392
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T]>, Tag>>
|
|
393
|
+
) => ApplyHKT<Type, [T]>)
|
|
394
|
+
: { readonly _tag: Tag } & Pipeable &
|
|
395
|
+
(<T extends _UpperBound<HKTParams<Type>[0]> = never>(
|
|
396
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T]>, Tag>>
|
|
397
|
+
) => ApplyHKT<Type, [T]>)
|
|
320
398
|
: Type extends TypeLambda<[never, never], unknown> ?
|
|
321
399
|
[unknown, unknown] extends (
|
|
322
400
|
[_UpperBound<HKTParams<Type>[0]>, _UpperBound<HKTParams<Type>[1]>]
|
|
323
401
|
) ?
|
|
324
|
-
{ readonly _tag: Tag } &
|
|
325
|
-
|
|
326
|
-
|
|
402
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
403
|
+
(<T = never, U = never>(
|
|
404
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
405
|
+
) => ApplyHKT<Type, [T, U]>)
|
|
327
406
|
: unknown extends _UpperBound<HKTParams<Type>[0]> ?
|
|
328
|
-
{ readonly _tag: Tag } &
|
|
329
|
-
T = never,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
333
|
-
) => ApplyHKT<Type, [T, U]>)
|
|
407
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
408
|
+
(<T = never, U extends _UpperBound<HKTParams<Type>[1]> = never>(
|
|
409
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
410
|
+
) => ApplyHKT<Type, [T, U]>)
|
|
334
411
|
: unknown extends _UpperBound<HKTParams<Type>[1]> ?
|
|
335
|
-
{ readonly _tag: Tag } &
|
|
412
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
413
|
+
(<T extends _UpperBound<HKTParams<Type>[0]> = never, U = never>(
|
|
414
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
415
|
+
) => ApplyHKT<Type, [T, U]>)
|
|
416
|
+
: { readonly _tag: Tag } & Pipeable &
|
|
417
|
+
(<
|
|
418
|
+
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
419
|
+
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
420
|
+
>(
|
|
421
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
422
|
+
) => ApplyHKT<Type, [T, U]>)
|
|
423
|
+
: Type extends TypeLambda<[never, never, never], unknown> ?
|
|
424
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
425
|
+
(<
|
|
336
426
|
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
337
|
-
U = never,
|
|
427
|
+
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
428
|
+
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
338
429
|
>(
|
|
339
|
-
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
340
|
-
) => ApplyHKT<Type, [T, U]>)
|
|
341
|
-
|
|
430
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V]>, Tag>>
|
|
431
|
+
) => ApplyHKT<Type, [T, U, V]>)
|
|
432
|
+
: Type extends TypeLambda<[never, never, never, never], unknown> ?
|
|
433
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
434
|
+
(<
|
|
342
435
|
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
343
436
|
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
437
|
+
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
438
|
+
W extends _UpperBound<HKTParams<Type>[3]> = never,
|
|
344
439
|
>(
|
|
345
|
-
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
|
|
346
|
-
) => ApplyHKT<Type, [T, U]>)
|
|
347
|
-
: Type extends TypeLambda<[never, never, never], unknown> ?
|
|
348
|
-
{ readonly _tag: Tag } & (<
|
|
349
|
-
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
350
|
-
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
351
|
-
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
352
|
-
>(
|
|
353
|
-
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V]>, Tag>>
|
|
354
|
-
) => ApplyHKT<Type, [T, U, V]>)
|
|
355
|
-
: Type extends TypeLambda<[never, never, never, never], unknown> ?
|
|
356
|
-
{ readonly _tag: Tag } & (<
|
|
357
|
-
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
358
|
-
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
359
|
-
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
360
|
-
W extends _UpperBound<HKTParams<Type>[3]> = never,
|
|
361
|
-
>(
|
|
362
|
-
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V, W]>, Tag>>
|
|
363
|
-
) => ApplyHKT<Type, [T, U, V, W]>)
|
|
440
|
+
...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V, W]>, Tag>>
|
|
441
|
+
) => ApplyHKT<Type, [T, U, V, W]>)
|
|
364
442
|
: Type extends TypeLambda<[never, never, never, never, never], unknown> ?
|
|
365
|
-
{ readonly _tag: Tag } &
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
443
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
444
|
+
(<
|
|
445
|
+
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
446
|
+
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
447
|
+
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
448
|
+
W extends _UpperBound<HKTParams<Type>[3]> = never,
|
|
449
|
+
X extends _UpperBound<HKTParams<Type>[4]> = never,
|
|
450
|
+
>(
|
|
451
|
+
...args: ExtractFields<
|
|
452
|
+
FilterTagged<ApplyHKT<Type, [T, U, V, W, X]>, Tag>
|
|
453
|
+
>
|
|
454
|
+
) => ApplyHKT<Type, [T, U, V, W, X]>)
|
|
374
455
|
: Type extends (
|
|
375
456
|
TypeLambda<[never, never, never, never, never, never], unknown>
|
|
376
457
|
) ?
|
|
377
|
-
{ readonly _tag: Tag } &
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
458
|
+
{ readonly _tag: Tag } & Pipeable &
|
|
459
|
+
(<
|
|
460
|
+
T extends _UpperBound<HKTParams<Type>[0]> = never,
|
|
461
|
+
U extends _UpperBound<HKTParams<Type>[1]> = never,
|
|
462
|
+
V extends _UpperBound<HKTParams<Type>[2]> = never,
|
|
463
|
+
W extends _UpperBound<HKTParams<Type>[3]> = never,
|
|
464
|
+
X extends _UpperBound<HKTParams<Type>[4]> = never,
|
|
465
|
+
Y extends _UpperBound<HKTParams<Type>[5]> = never,
|
|
466
|
+
>(
|
|
467
|
+
...args: ExtractFields<
|
|
468
|
+
FilterTagged<ApplyHKT<Type, [T, U, V, W, X, Y]>, Tag>
|
|
469
|
+
>
|
|
470
|
+
) => ApplyHKT<Type, [T, U, V, W, X, Y]>)
|
|
389
471
|
: /* support up to 6 type parameters */ never;
|
|
390
472
|
|
|
391
473
|
/**
|
|
@@ -1412,7 +1494,7 @@ type HKTParams<F> =
|
|
|
1412
1494
|
* type _1 = TolerantResult<OptionHKT>; // => Option<unknown>
|
|
1413
1495
|
* ```
|
|
1414
1496
|
*/
|
|
1415
|
-
|
|
1497
|
+
type TolerantResult<F extends TypeLambda> =
|
|
1416
1498
|
HKTParams<F> extends infer Params extends unknown[] ?
|
|
1417
1499
|
ApplyHKT<
|
|
1418
1500
|
F,
|
|
@@ -1453,3 +1535,6 @@ type _CheckVariance<Lower, Upper> =
|
|
|
1453
1535
|
: "covariant"
|
|
1454
1536
|
: [Upper] extends [Lower] ? "contravariant"
|
|
1455
1537
|
: "invariant";
|
|
1538
|
+
|
|
1539
|
+
/* Ensure TypeScript treats this file as a module to prevent internal from exportation */
|
|
1540
|
+
export {};
|
package/index.js
CHANGED
|
@@ -28,17 +28,21 @@ export function make(variants) {
|
|
|
28
28
|
|
|
29
29
|
/* Constructor */
|
|
30
30
|
const createConstructor = (tag) =>
|
|
31
|
-
Object.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
Object.setPrototypeOf(
|
|
32
|
+
Object.assign(
|
|
33
|
+
renameFunction((...args) => {
|
|
34
|
+
const result = Object.create(PipeableProto);
|
|
35
|
+
result._tag = tag;
|
|
36
|
+
for (let i = 0; i < args.length; i++) result["_" + i] = args[i];
|
|
37
|
+
return result;
|
|
38
|
+
}, tag),
|
|
39
|
+
{
|
|
40
|
+
_tag: tag,
|
|
41
|
+
toJSON: () => ({ _tag: tag }),
|
|
42
|
+
[Symbol.for("nodejs.util.inspect.custom")]: () => ({ _tag: tag }),
|
|
43
|
+
},
|
|
44
|
+
),
|
|
45
|
+
PipeableFunctionProto,
|
|
42
46
|
);
|
|
43
47
|
|
|
44
48
|
const result = {
|
|
@@ -344,3 +348,42 @@ const stringify = (value) => {
|
|
|
344
348
|
|
|
345
349
|
return serialize(value, []);
|
|
346
350
|
};
|
|
351
|
+
|
|
352
|
+
export const PipeableProto = {
|
|
353
|
+
pipe(...fs) {
|
|
354
|
+
// Optimization inspired by Effect
|
|
355
|
+
// https://github.com/Effect-TS/effect/blob/f293e97ab2a26f45586de106b85119c5d98ab4c7/packages/effect/src/Pipeable.ts#L491-L524
|
|
356
|
+
switch (fs.length) {
|
|
357
|
+
case 0:
|
|
358
|
+
return this;
|
|
359
|
+
case 1:
|
|
360
|
+
return fs[0](this);
|
|
361
|
+
case 2:
|
|
362
|
+
return fs[1](fs[0](this));
|
|
363
|
+
case 3:
|
|
364
|
+
return fs[2](fs[1](fs[0](this)));
|
|
365
|
+
case 4:
|
|
366
|
+
return fs[3](fs[2](fs[1](fs[0](this))));
|
|
367
|
+
case 5:
|
|
368
|
+
return fs[4](fs[3](fs[2](fs[1](fs[0](this)))));
|
|
369
|
+
case 6:
|
|
370
|
+
return fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this))))));
|
|
371
|
+
case 7:
|
|
372
|
+
return fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this)))))));
|
|
373
|
+
case 8:
|
|
374
|
+
return fs[7](fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this))))))));
|
|
375
|
+
case 9:
|
|
376
|
+
return fs[8](
|
|
377
|
+
fs[7](fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this)))))))),
|
|
378
|
+
);
|
|
379
|
+
default: {
|
|
380
|
+
let result = this;
|
|
381
|
+
for (const f of fs) result = f(result);
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const PipeableFunctionProto = { pipe: PipeableProto.pipe };
|
|
389
|
+
Object.setPrototypeOf(PipeableFunctionProto, Function.prototype);
|
package/package.json
CHANGED
package/utils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ShowOptions } from "showify";
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* Print arguments including (possibly) ADTs to `stdout` with newline.
|
|
5
4
|
* @param args The arguments to print.
|
|
@@ -25,7 +24,6 @@ import type { ShowOptions } from "showify";
|
|
|
25
24
|
* @see {@linkcode show} if you want more control over the output.
|
|
26
25
|
*/
|
|
27
26
|
export declare function println(...args: unknown[]): void;
|
|
28
|
-
|
|
29
27
|
/**
|
|
30
28
|
* Stringify a (possibly) ADT to human-readable format.
|
|
31
29
|
* @param value The value to stringify.
|
package/utils.js
CHANGED
|
@@ -29,8 +29,10 @@ const { between, pair, sequence, text, variant } = SerializerNode;
|
|
|
29
29
|
* @see {@linkcode show} if you want more control over the output.
|
|
30
30
|
*/
|
|
31
31
|
export function println(...args) {
|
|
32
|
-
|
|
33
|
-
...args.map((arg) =>
|
|
32
|
+
console.log(
|
|
33
|
+
...args.map((arg) =>
|
|
34
|
+
typeof arg === "string" ? arg : show(arg, { colors: true, indent: 2 }),
|
|
35
|
+
),
|
|
34
36
|
);
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -103,7 +105,9 @@ export function show(value, options = {}) {
|
|
|
103
105
|
sequence([
|
|
104
106
|
text(c.cyan(val._tag) + "("),
|
|
105
107
|
...flatMap(fields, (field, i, arr) =>
|
|
106
|
-
i === arr.length - 1 ?
|
|
108
|
+
i === arr.length - 1 ?
|
|
109
|
+
expand(field)
|
|
110
|
+
: [expand(field), text(", ")],
|
|
107
111
|
),
|
|
108
112
|
...(body.type === "text" ? [text(")")] : [text(") "), body]),
|
|
109
113
|
]),
|
|
@@ -150,19 +154,3 @@ const flatMap = (arr, fn) => {
|
|
|
150
154
|
}
|
|
151
155
|
return result;
|
|
152
156
|
};
|
|
153
|
-
|
|
154
|
-
// `console` is not standard in JavaScript. Though rare, it is possible that `console` is not
|
|
155
|
-
// available in some environments. We use a proxy to handle this case and ignore errors if `console`
|
|
156
|
-
// is not available.
|
|
157
|
-
const getConsole = (() => {
|
|
158
|
-
let cachedConsole = undefined;
|
|
159
|
-
return () => {
|
|
160
|
-
if (cachedConsole !== undefined) return cachedConsole;
|
|
161
|
-
try {
|
|
162
|
-
cachedConsole = new Function("return console")();
|
|
163
|
-
} catch {
|
|
164
|
-
cachedConsole = null;
|
|
165
|
-
}
|
|
166
|
-
return cachedConsole;
|
|
167
|
-
};
|
|
168
|
-
})();
|