kind-adt 0.2.0 → 0.2.1

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.
Files changed (4) hide show
  1. package/README.md +90 -1
  2. package/index.d.ts +93 -16
  3. package/index.js +55 -20
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -597,12 +597,101 @@ import { show } from "showify";
597
597
  export function println(...args: unknown[]) {
598
598
  console.log(
599
599
  ...args.map((arg) =>
600
- typeof arg === "string" ? arg : show(arg, { colors: true, trailingComma: "true", indent: 2 }),
600
+ typeof arg === "string" ? arg : show(arg, { colors: true, trailingComma: "auto", indent: 2 }),
601
601
  ),
602
602
  );
603
603
  }
604
604
  ```
605
605
 
606
+ ### Add your own methods to ADTs
607
+
608
+ > [!WARNING]
609
+ >
610
+ > This feature is not recommended for most users, as it may lead to unexpected behavior while module resolution. Use it at your own risk.
611
+
612
+ ADTs and ADT constructors in kind-adt use a prototype chain to provide “methods” like `.pipe()`. Due to the nature of how prototypes work in JavaScript, you can add your own methods (or “[monkey patch](https://en.wikipedia.org/wiki/Monkey_patch)”) to ADTs or ADT constructors by modifying the prototype of the ADT or ADT constructor.
613
+
614
+ kind-adt exports four prototypes for you to use, including the `PipeableProto` mentioned in the [Functional pipelines with `.pipe()`](#functional-pipelines-with-pipe) section:
615
+
616
+ ```typescript
617
+ import {
618
+ type Pipeable,
619
+ PipeableProto,
620
+ type PipeableFunction,
621
+ PipeableFunctionProto,
622
+ type ADT,
623
+ ADTProto,
624
+ type ADTConstructor,
625
+ ADTConstructorProto,
626
+ } from "kind-adt";
627
+ ```
628
+
629
+ Each `XxxProto` has a related `Xxx` type, which is the type of the object that can be created from the prototype. ADTs and ADT constructors in kind-adt follow the following prototype chain:
630
+
631
+ ```typescript
632
+ ╔══════════════════════════════════╗ ╔════════════╗ ╔═════════════════╗
633
+ ║ Concrete ADT (e.g., `Some(...)`) ║ ← ║ `ADTProto` ║ ← ║ `PipeableProto` ║
634
+ ╚══════════════════════════════════╝ ╚════════════╝ ╚═════════════════╝
635
+
636
+ ╔═════════════════════════════════════════╗ ╔═══════════════════════╗ ╔═════════════════════════╗
637
+ ║ Concrete ADT constructor (e.g., `None`) ║ ← ║ `ADTConstructorProto` ║ ← ║ `PipeableFunctionProto` ║
638
+ ╚═════════════════════════════════════════╝ ╚═══════════════════════╝ ╚═════════════════════════╝
639
+ ```
640
+
641
+ Note that though ADTs and ADT constructors share the same `.pipe()` method, they actually have independent prototype chains. This means that you have to patch both prototypes if you want to add your own methods to both ADTs and ADT constructors.
642
+
643
+ The following example shows how to add a `.println()` method to add ADTs and ADT constructors with type safety. We’ll create a `patches.ts` file to add the method to the prototypes of ADTs and ADT constructors.
644
+
645
+ ```typescript
646
+ // patches.ts
647
+ import { type ADT, ADTProto, type ADTConstructor, ADTConstructorProto } from "kind-adt";
648
+ import { show } from "showify";
649
+
650
+ /* Make TypeScript aware of the new method with a module augmentation
651
+ https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation */
652
+ declare module "kind-adt" {
653
+ interface ADT {
654
+ println(): void;
655
+ }
656
+
657
+ interface ADTConstructor {
658
+ println(): void;
659
+ }
660
+ }
661
+
662
+ /* Add the method to the ADT prototype */
663
+ ADTProto.println = function println(this: ADT) {
664
+ console.log(show(this, { colors: true, trailingComma: "auto", indent: 2 }));
665
+ };
666
+ ADTConstructorProto.println = function println(this: ADTConstructor) {
667
+ console.log(show(this, { colors: true, trailingComma: "auto", indent: 2 }));
668
+ };
669
+
670
+ /* Ensure TypeScript treats this file as a module */
671
+ export {};
672
+ ```
673
+
674
+ Then you can import the `patches.ts` file in your main file to apply the patches:
675
+
676
+ ```typescript
677
+ import "./patches"; // Import the patches file
678
+
679
+ import { type Data, make } from "kind-adt";
680
+
681
+ type Option<T> = Data<{
682
+ Some: [value: T];
683
+ None: [];
684
+ }>;
685
+
686
+ const { Some, None } = make<OptionHKT>();
687
+ interface OptionHKT extends HKT {
688
+ return: Option<Arg0<this>>;
689
+ }
690
+
691
+ Some(42).println(); // Prints: Some(42)
692
+ None.println(); // Prints: None
693
+ ```
694
+
606
695
  ## FAQ
607
696
 
608
697
  ### I don’t want to install another package for HKT. Can I implement my own?
package/index.d.ts CHANGED
@@ -126,12 +126,89 @@ export interface Pipeable {
126
126
  // prettier-ignore
127
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
128
  }
129
-
130
- /**
131
- * The prototype to build a {@linkcode Pipeable} object.
132
- */
129
+ /** The prototype to build a {@linkcode Pipeable} object. */
133
130
  export const PipeableProto: Pipeable;
134
131
 
132
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
133
+ export interface PipeableFunction extends Function {
134
+ /**
135
+ * Pipe the value through a series of functions.
136
+ *
137
+ * **Example**
138
+ *
139
+ * ```typescript
140
+ * import { type Data, make } from "kind-adt";
141
+ *
142
+ * type BoxNumber = Data<{
143
+ * Box: [number];
144
+ * }>;
145
+ * const { Box } = make<BoxNumber>();
146
+ *
147
+ * Box(42).pipe((box) => box._0 + 1, (n) => n * 2, (n) => n.toString()); // => "86"
148
+ * ```
149
+ */
150
+ pipe<A>(this: A): A;
151
+ pipe<A, B = never>(this: A, ab: (a: A) => B): B;
152
+ // prettier-ignore
153
+ pipe<A, B = never, C = never>(this: A, ab: (a: A) => B, bc: (b: B) => C): C;
154
+ // prettier-ignore
155
+ pipe<A, B = never, C = never, D = never>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;
156
+ // prettier-ignore
157
+ 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;
158
+ // prettier-ignore
159
+ 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;
160
+ // prettier-ignore
161
+ 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;
162
+ // prettier-ignore
163
+ 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;
164
+ // prettier-ignore
165
+ 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;
166
+ // prettier-ignore
167
+ 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;
168
+ // prettier-ignore
169
+ 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;
170
+ // prettier-ignore
171
+ 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;
172
+ // prettier-ignore
173
+ 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;
174
+ // prettier-ignore
175
+ 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;
176
+ // prettier-ignore
177
+ 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;
178
+ // prettier-ignore
179
+ 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;
180
+ // prettier-ignore
181
+ 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;
182
+ // prettier-ignore
183
+ 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;
184
+ // prettier-ignore
185
+ 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;
186
+ // prettier-ignore
187
+ 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;
188
+ // prettier-ignore
189
+ 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;
190
+ // prettier-ignore
191
+ 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;
192
+ // prettier-ignore
193
+ 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;
194
+ // prettier-ignore
195
+ 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;
196
+ // prettier-ignore
197
+ 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;
198
+ // prettier-ignore
199
+ 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;
200
+ }
201
+ /** The prototype to build a {@linkcode PipeableFunction}. */
202
+ export const PipeableFunctionProto: PipeableFunction;
203
+
204
+ export interface ADT extends Pipeable {}
205
+ /** The prototype of ADTs. */
206
+ export const ADTProto: ADT;
207
+
208
+ export interface ADTConstructor extends PipeableFunction {}
209
+ /** The prototype of ADT constructors. */
210
+ export const ADTConstructorProto: ADTConstructor;
211
+
135
212
  /**************
136
213
  * Main types *
137
214
  **************/
@@ -172,7 +249,7 @@ export type Tagged<
172
249
  { readonly [I in IndexOf<Fields> as `_${I}`]: Fields[I] }
173
250
  : never
174
251
  > &
175
- Pipeable;
252
+ ADT;
176
253
 
177
254
  /**
178
255
  * Create an ADT with tagged types.
@@ -382,16 +459,16 @@ export type Constructor<
382
459
  [Type] extends (
383
460
  [Tagged] // Non-generic ADT
384
461
  ) ?
385
- { readonly _tag: Tag } & Pipeable &
462
+ { readonly _tag: Tag } & ADT &
386
463
  ((...args: ExtractFields<Extract<Type, Tagged<Tag>>>) => Type)
387
464
  : // Generic ADT
388
465
  Type extends TypeLambda<[never], unknown> ?
389
466
  unknown extends _UpperBound<HKTParams<Type>[0]> ?
390
- { readonly _tag: Tag } & Pipeable &
467
+ { readonly _tag: Tag } & ADT &
391
468
  (<T = never>(
392
469
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T]>, Tag>>
393
470
  ) => ApplyHKT<Type, [T]>)
394
- : { readonly _tag: Tag } & Pipeable &
471
+ : { readonly _tag: Tag } & ADT &
395
472
  (<T extends _UpperBound<HKTParams<Type>[0]> = never>(
396
473
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T]>, Tag>>
397
474
  ) => ApplyHKT<Type, [T]>)
@@ -399,21 +476,21 @@ export type Constructor<
399
476
  [unknown, unknown] extends (
400
477
  [_UpperBound<HKTParams<Type>[0]>, _UpperBound<HKTParams<Type>[1]>]
401
478
  ) ?
402
- { readonly _tag: Tag } & Pipeable &
479
+ { readonly _tag: Tag } & ADT &
403
480
  (<T = never, U = never>(
404
481
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
405
482
  ) => ApplyHKT<Type, [T, U]>)
406
483
  : unknown extends _UpperBound<HKTParams<Type>[0]> ?
407
- { readonly _tag: Tag } & Pipeable &
484
+ { readonly _tag: Tag } & ADT &
408
485
  (<T = never, U extends _UpperBound<HKTParams<Type>[1]> = never>(
409
486
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
410
487
  ) => ApplyHKT<Type, [T, U]>)
411
488
  : unknown extends _UpperBound<HKTParams<Type>[1]> ?
412
- { readonly _tag: Tag } & Pipeable &
489
+ { readonly _tag: Tag } & ADT &
413
490
  (<T extends _UpperBound<HKTParams<Type>[0]> = never, U = never>(
414
491
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
415
492
  ) => ApplyHKT<Type, [T, U]>)
416
- : { readonly _tag: Tag } & Pipeable &
493
+ : { readonly _tag: Tag } & ADT &
417
494
  (<
418
495
  T extends _UpperBound<HKTParams<Type>[0]> = never,
419
496
  U extends _UpperBound<HKTParams<Type>[1]> = never,
@@ -421,7 +498,7 @@ export type Constructor<
421
498
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U]>, Tag>>
422
499
  ) => ApplyHKT<Type, [T, U]>)
423
500
  : Type extends TypeLambda<[never, never, never], unknown> ?
424
- { readonly _tag: Tag } & Pipeable &
501
+ { readonly _tag: Tag } & ADT &
425
502
  (<
426
503
  T extends _UpperBound<HKTParams<Type>[0]> = never,
427
504
  U extends _UpperBound<HKTParams<Type>[1]> = never,
@@ -430,7 +507,7 @@ export type Constructor<
430
507
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V]>, Tag>>
431
508
  ) => ApplyHKT<Type, [T, U, V]>)
432
509
  : Type extends TypeLambda<[never, never, never, never], unknown> ?
433
- { readonly _tag: Tag } & Pipeable &
510
+ { readonly _tag: Tag } & ADT &
434
511
  (<
435
512
  T extends _UpperBound<HKTParams<Type>[0]> = never,
436
513
  U extends _UpperBound<HKTParams<Type>[1]> = never,
@@ -440,7 +517,7 @@ export type Constructor<
440
517
  ...args: ExtractFields<FilterTagged<ApplyHKT<Type, [T, U, V, W]>, Tag>>
441
518
  ) => ApplyHKT<Type, [T, U, V, W]>)
442
519
  : Type extends TypeLambda<[never, never, never, never, never], unknown> ?
443
- { readonly _tag: Tag } & Pipeable &
520
+ { readonly _tag: Tag } & ADT &
444
521
  (<
445
522
  T extends _UpperBound<HKTParams<Type>[0]> = never,
446
523
  U extends _UpperBound<HKTParams<Type>[1]> = never,
@@ -455,7 +532,7 @@ export type Constructor<
455
532
  : Type extends (
456
533
  TypeLambda<[never, never, never, never, never, never], unknown>
457
534
  ) ?
458
- { readonly _tag: Tag } & Pipeable &
535
+ { readonly _tag: Tag } & ADT &
459
536
  (<
460
537
  T extends _UpperBound<HKTParams<Type>[0]> = never,
461
538
  U extends _UpperBound<HKTParams<Type>[1]> = never,
package/index.js CHANGED
@@ -36,11 +36,7 @@ export function make(variants) {
36
36
  for (let i = 0; i < args.length; i++) result["_" + i] = args[i];
37
37
  return result;
38
38
  }, tag),
39
- {
40
- _tag: tag,
41
- toJSON: () => ({ _tag: tag }),
42
- [Symbol.for("nodejs.util.inspect.custom")]: () => ({ _tag: tag }),
43
- }
39
+ { _tag: tag }
44
40
  ),
45
41
  ADTConstructorProto
46
42
  );
@@ -394,6 +390,29 @@ function inspect({ ancestors, c, level }, expand) {
394
390
  body = body.values[2];
395
391
  }
396
392
 
393
+ let shouldCollapse = false;
394
+ let firstFieldNode;
395
+ if (fields.length === 1) {
396
+ firstFieldNode = expand(fields[0]);
397
+ shouldCollapse =
398
+ firstFieldNode.type === "between" ||
399
+ (firstFieldNode.type === "variant" &&
400
+ firstFieldNode.inline.type === "between" &&
401
+ firstFieldNode.wrap.type === "between") ||
402
+ (firstFieldNode.type === "sequence" &&
403
+ firstFieldNode.values.slice(0, -1).every((v) => v.type === "text") &&
404
+ firstFieldNode.values[firstFieldNode.values.length - 1].type ===
405
+ "between") ||
406
+ (firstFieldNode.type === "sequence" &&
407
+ firstFieldNode.values.slice(0, -1).every((v) => v.type === "text") &&
408
+ firstFieldNode.values[firstFieldNode.values.length - 1].type ===
409
+ "variant" &&
410
+ firstFieldNode.values[firstFieldNode.values.length - 1].inline.type ===
411
+ "between" &&
412
+ firstFieldNode.values[firstFieldNode.values.length - 1].wrap.type ===
413
+ "between");
414
+ }
415
+
397
416
  return (
398
417
  fields.length ?
399
418
  variant(
@@ -405,17 +424,25 @@ function inspect({ ancestors, c, level }, expand) {
405
424
  ...(body.type === "text" ? [text(")")] : [text(") "), body]),
406
425
  ]),
407
426
  body.type === "text" ?
408
- between(
409
- fields.map((field) => pair(expand(field), text(","))),
410
- text(c.cyan(this._tag) + "("),
411
- text(")")
412
- )
413
- : pair(
414
- between(
427
+ shouldCollapse ?
428
+ sequence([text(c.cyan(this._tag) + "("), firstFieldNode, text(")")])
429
+ : between(
415
430
  fields.map((field) => pair(expand(field), text(","))),
416
431
  text(c.cyan(this._tag) + "("),
417
- text(") ")
418
- ),
432
+ text(")")
433
+ )
434
+ : pair(
435
+ shouldCollapse ?
436
+ sequence([
437
+ text(c.cyan(this._tag) + "("),
438
+ firstFieldNode,
439
+ text(") "),
440
+ ])
441
+ : between(
442
+ fields.map((field) => pair(expand(field), text(","))),
443
+ text(c.cyan(this._tag) + "("),
444
+ text(") ")
445
+ ),
419
446
  body
420
447
  )
421
448
  )
@@ -470,10 +497,18 @@ export const PipeableProto = {
470
497
  },
471
498
  };
472
499
 
473
- const ADTProto = {
474
- ...PipeableProto,
475
- [Symbol.for("showify.inspect.custom")]: inspect,
476
- };
500
+ export const PipeableFunctionProto = { ...PipeableProto };
501
+ Object.setPrototypeOf(PipeableFunctionProto, Function.prototype);
502
+
503
+ export const ADTProto = Object.create(PipeableProto);
504
+ ADTProto[Symbol.for("showify.inspect.custom")] = inspect;
477
505
 
478
- const ADTConstructorProto = { ...ADTProto };
479
- Object.setPrototypeOf(ADTConstructorProto, Function.prototype);
506
+ export const ADTConstructorProto = Object.create(PipeableFunctionProto);
507
+ ADTConstructorProto.toJSON = function toJSON() {
508
+ return { _tag: this.tag };
509
+ };
510
+ ADTConstructorProto[Symbol.for("nodejs.util.inspect.custom")] =
511
+ function inspect() {
512
+ return { _tag: this.tag };
513
+ };
514
+ ADTConstructorProto[Symbol.for("showify.inspect.custom")] = inspect;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kind-adt",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "🪴 The kind of ADTs you can count on in TypeScript",
5
5
  "keywords": [
6
6
  "typescript",