kind-adt 0.1.2 → 0.2.0

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 CHANGED
@@ -58,8 +58,8 @@ match(safeDivide(42, 2), {
58
58
  - Support for **functional pipelines** with a [`.pipe()` method](#functional-pipelines-with-pipe) on all ADTs.
59
59
  - [**Readable type signatures**](#provide-more-readable-type-signatures) for your ADT with _labeled tuples_.
60
60
  - [**Recursive ADTs**](#recursive-adts) with ease.
61
- - Tiny footprint (~1kB minzipped).
62
- - Debug your ADTs with [optional utilities](#optional-utilities) ([`println`](#println) and [`show`](#show)) from `kind-adt/utils`.
61
+ - Tiny footprint (~2kB minzipped).
62
+ - Convert your ADTs to human-readable strings with [showify](https://github.com/Snowflyt/showify) integration.
63
63
 
64
64
  ## Installation
65
65
 
@@ -95,7 +95,7 @@ You can create **constructors**, **deconstructors** and **type guards** using th
95
95
 
96
96
  ```typescript
97
97
  import { make } from "kind-adt";
98
- import { println } from "kind-adt/utils";
98
+ import { show } from "showify"; // Optional dependency
99
99
  import type { Arg0, HKT } from "hkt-core";
100
100
 
101
101
  export const { Some, None, match: matchOption, isSome, ifSome /* ... */ } = make<OptionHKT>();
@@ -106,8 +106,9 @@ interface OptionHKT extends HKT {
106
106
  Some(42); // => { _tag: "Some", _0: 42 }
107
107
  // ^?: <number>(args_0: number) => Option<number>
108
108
 
109
- // Use `println` to print the ADT in a readable format
110
- println(Some(42)); // Some(42)
109
+ // Use `show` from showify to print the ADT in a readable format
110
+ console.log(show(Some(42), { indent: 2, trailingComma: "auto", colors: true }));
111
+ // Some(42)
111
112
  ```
112
113
 
113
114
  <details>
@@ -123,9 +124,6 @@ export const IpAddr = make<IpAddr>();
123
124
 
124
125
  IpAddr.V4(127, 0, 0, 1); // => { _tag: "V4", _0: 127, _1: 0, _2: 0, _3: 1 }
125
126
  IpAddr.V6("::1"); // => { _tag: "V6", _0: "::1" }
126
-
127
- println(IpAddr.V4(127, 0, 0, 1)); // V4(127, 0, 0, 1)
128
- println(IpAddr.V6("::1")); // V6("::1")
129
127
  ```
130
128
 
131
129
  </details>
@@ -224,7 +222,7 @@ matchOption(Some(42), {
224
222
  - Check out the [syntax sugar for ADTs with only one object field](#syntax-sugar-for-adts-with-only-one-object-field) and [recursive ADTs](#recursive-adts).
225
223
  - See how to [check the type of an ADT with **type guards** and extract the fields with **`unwrap`**](#type-guards-and-unwrap).
226
224
  - Check out the [conditional deconstructors](#conditional-deconstructors-if) if you are tired with using `match` on a single variant with a verbose catch-all case.
227
- - See how to use [optional utilities](#optional-utilities) like `println` and `show` to debug your ADTs with ease.
225
+ - See how to use [showify](#convert-adts-to-human-readable-strings) to convert your ADTs to human-readable strings.
228
226
 
229
227
  ## Recipes
230
228
 
@@ -560,18 +558,20 @@ const result = Option.ifSome(
560
558
  );
561
559
  ```
562
560
 
563
- ## Optional Utilities
561
+ ### Convert ADTs to human-readable strings
564
562
 
565
- > [!NOTE]
566
- >
567
- > To use the `println` and `show` utilities, the [showify](https://github.com/Snowflyt/showify) package is required to be installed.
563
+ kind-adt provides integration with the [showify](https://github.com/Snowflyt/showify) package, which allows you to convert objects to human-readable strings. This is especially useful for debugging and logging purposes.
568
564
 
569
- ### `println`
565
+ To use this feature, you need to install the [showify](https://github.com/Snowflyt/showify) package:
570
566
 
571
- You can use the `println` function to print an ADT in a readable format, which is especially useful for debugging.
567
+ ```shell
568
+ npm install showify
569
+ ```
572
570
 
573
- ```typescript
574
- import { println } from "kind-adt/utils";
571
+ Then you can use the `show` function to convert an ADT to a human-readable string.
572
+
573
+ ```javascript
574
+ import { show } from "showify";
575
575
 
576
576
  // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
577
577
  const tree = Tree.Node(
@@ -580,8 +580,8 @@ const tree = Tree.Node(
580
580
  Tree.Node(4, Tree.Empty, Tree.Node(3, Tree.Empty, Tree.Empty)),
581
581
  );
582
582
 
583
- // ANSI colors are supported
584
- println(tree);
583
+ // Print the ADT with ANSI colors and indented format
584
+ console.log(show(tree, { indent: 2, trailingComma: "auto", colors: true }));
585
585
  // Node(
586
586
  // 1,
587
587
  // Node(2, Node(3, Empty, Empty), Empty),
@@ -589,31 +589,18 @@ println(tree);
589
589
  // )
590
590
  ```
591
591
 
592
- Check out [`show`](#show) if you want more control over the output.
593
-
594
- ### `show`
595
-
596
- The `println` utility uses the [showify](https://github.com/Snowflyt/showify) package to convert an ADT into a string. Since `println` accepts variadic arguments, it does not support passing options to control the output. If you want more control over the output, you can use the `show` function to convert an ADT into a string, which accepts an optional `ShowOptions` object from the showify package to control the output.
592
+ If you find it tedious to write `console.log(show(...))` every time, you can create a utility function to print the ADT directly:
597
593
 
598
- ```typescript
599
- import { show } from "kind-adt/utils";
600
-
601
- // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
602
- const tree = Tree.Node(1, Tree.Node(2, Tree.Empty, Tree.Empty), Tree.Empty);
603
-
604
- console.log(show(tree));
605
- // Node(1, Node(2, Empty, Empty), Empty)
594
+ ```javascript
595
+ import { show } from "showify";
606
596
 
607
- console.log(show(tree, { indent: 4, breakLength: 0, trailingComma: "auto" }));
608
- // Node(
609
- // 1,
610
- // Node(
611
- // 2,
612
- // Empty,
613
- // Empty,
614
- // ),
615
- // Empty,
616
- // )
597
+ export function println(...args: unknown[]) {
598
+ console.log(
599
+ ...args.map((arg) =>
600
+ typeof arg === "string" ? arg : show(arg, { colors: true, trailingComma: "true", indent: 2 }),
601
+ ),
602
+ );
603
+ }
617
604
  ```
618
605
 
619
606
  ## FAQ
package/index.d.ts CHANGED
@@ -19,13 +19,13 @@
19
19
  * @see {@linkcode Data} for details on how to create an ADT.
20
20
  */
21
21
  export function make<F extends Tagged | TypeLambda<never, Tagged>>(
22
- variants?: readonly Instantiate<F>["_tag"][],
22
+ variants?: readonly Instantiate<F>["_tag"][]
23
23
  ): Instantiate<F> extends infer Type extends Tagged ?
24
24
  Spread<
25
25
  { readonly [Tag in Type["_tag"] as Tag]: Constructor<F, Tag> },
26
26
  {
27
27
  readonly [Tag in Type["_tag"] as `is${Tag}`]: (
28
- adt: Type,
28
+ adt: Type
29
29
  ) => adt is FilterTagged<Type, Tag>;
30
30
  },
31
31
  { readonly unwrap: Deconstructor<Type> },
@@ -474,14 +474,14 @@ export type Constructor<
474
474
  * A type guard function for an ADT.
475
475
  */
476
476
  export type Guard<T extends Tagged, Tag extends string> = (
477
- adt: T,
477
+ adt: T
478
478
  ) => adt is FilterTagged<T, Tag>;
479
479
 
480
480
  /**
481
481
  * A deconstructor for an ADT.
482
482
  */
483
483
  export type Deconstructor<Type extends Tagged> = <T extends Type>(
484
- adt: T,
484
+ adt: T
485
485
  ) => ExtractFields<T>;
486
486
 
487
487
  type ConditionalDeconstructorOf<
@@ -492,7 +492,7 @@ type ConditionalDeconstructorOf<
492
492
  <R1, R2 = void>(
493
493
  adt: F,
494
494
  onMatch: (...args: ExtractFields<FilterTagged<F, Tag>>) => R1,
495
- otherwise?: (adt: Exclude<F, Tagged<Tag>>) => R2,
495
+ otherwise?: (adt: Exclude<F, Tagged<Tag>>) => R2
496
496
  ) => R1 | R2
497
497
  : [F] extends [TypeLambda<[never], Tagged>] ?
498
498
  ConditionalDeconstructor1<F, Tag>
@@ -510,14 +510,14 @@ type ConditionalDeconstructor1<
510
510
  onMatch: (
511
511
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
512
512
  ) => R1,
513
- otherwise?: (adt: Exclude<ApplyHKT<F, [T]>, Tagged<Tag>>) => R2,
513
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T]>, Tagged<Tag>>) => R2
514
514
  ) => R1 | R2
515
515
  : <T extends HKTParams<F>[0], R1, R2 = void>(
516
516
  adt: ApplyHKT<F, [T]>,
517
517
  onMatch: (
518
518
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
519
519
  ) => R1,
520
- otherwise?: (adt: Exclude<ApplyHKT<F, [T]>, Tagged<Tag>>) => R2,
520
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T]>, Tagged<Tag>>) => R2
521
521
  ) => R1 | R2;
522
522
 
523
523
  type ConditionalDeconstructor2<
@@ -530,7 +530,7 @@ type ConditionalDeconstructor2<
530
530
  onMatch: (
531
531
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
532
532
  ) => R1,
533
- otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2,
533
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2
534
534
  ) => R1 | R2
535
535
  : unknown extends HKTParams<F>[0] ?
536
536
  <T, U extends HKTParams<F>[1], R1, R2 = void>(
@@ -538,7 +538,7 @@ type ConditionalDeconstructor2<
538
538
  onMatch: (
539
539
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
540
540
  ) => R1,
541
- otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2,
541
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2
542
542
  ) => R1 | R2
543
543
  : unknown extends HKTParams<F>[1] ?
544
544
  <T extends HKTParams<F>[0], U, R1, R2 = void>(
@@ -546,14 +546,14 @@ type ConditionalDeconstructor2<
546
546
  onMatch: (
547
547
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
548
548
  ) => R1,
549
- otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2,
549
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2
550
550
  ) => R1 | R2
551
551
  : <T extends HKTParams<F>[0], U extends HKTParams<F>[1], R1, R2 = void>(
552
552
  adt: ApplyHKT<F, [T, U]>,
553
553
  onMatch: (
554
554
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
555
555
  ) => R1,
556
- otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2,
556
+ otherwise?: (adt: Exclude<ApplyHKT<F, [T, U]>, Tagged<Tag>>) => R2
557
557
  ) => R1 | R2;
558
558
 
559
559
  // Fallback conditional deconstructor type
@@ -566,7 +566,7 @@ export type ConditionalDeconstructor<
566
566
  > = <T extends Type, R1, R2 = void>(
567
567
  adt: T,
568
568
  onMatch: (...args: ExtractFields<FilterTagged<T, Tag>>) => R1,
569
- otherwise?: (adt: Exclude<T, Tagged<Tag>>) => R2,
569
+ otherwise?: (adt: Exclude<T, Tagged<Tag>>) => R2
570
570
  ) => R1 | R2;
571
571
 
572
572
  type MatcherOf<F extends Tagged | TypeLambda<never, Tagged>> =
@@ -578,7 +578,7 @@ type MatcherOf<F extends Tagged | TypeLambda<never, Tagged>> =
578
578
  readonly [Tag in F["_tag"]]: (
579
579
  ...args: ExtractFields<FilterTagged<F, Tag>>
580
580
  ) => R;
581
- },
581
+ }
582
582
  ): R;
583
583
  <R>(
584
584
  adt: F,
@@ -586,7 +586,7 @@ type MatcherOf<F extends Tagged | TypeLambda<never, Tagged>> =
586
586
  readonly [Tag in F["_tag"]]?: (
587
587
  ...args: ExtractFields<FilterTagged<F, Tag>>
588
588
  ) => R;
589
- } & { _: (adt: F) => R },
589
+ } & { _: (adt: F) => R }
590
590
  ): R;
591
591
  <R>(cases: {
592
592
  readonly [Tag in F["_tag"]]: (
@@ -598,7 +598,7 @@ type MatcherOf<F extends Tagged | TypeLambda<never, Tagged>> =
598
598
  readonly [Tag in F["_tag"]]?: (
599
599
  ...args: ExtractFields<FilterTagged<F, Tag>>
600
600
  ) => R;
601
- } & { _: (adt: F) => R },
601
+ } & { _: (adt: F) => R }
602
602
  ): (adt: F) => R;
603
603
  }
604
604
  : [F] extends [TypeLambda<[never], Tagged>] ? Matcher1<F>
@@ -614,7 +614,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
614
614
  readonly [Tag in Instantiate<F>["_tag"]]: (
615
615
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
616
616
  ) => R;
617
- },
617
+ }
618
618
  ): R;
619
619
  <T, R>(
620
620
  adt: ApplyHKT<F, [T]>,
@@ -622,7 +622,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
622
622
  readonly [Tag in Instantiate<F>["_tag"]]?: (
623
623
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
624
624
  ) => R;
625
- } & { _: (adt: ApplyHKT<F, [T]>) => R },
625
+ } & { _: (adt: ApplyHKT<F, [T]>) => R }
626
626
  ): R;
627
627
  <T, R>(cases: {
628
628
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -634,7 +634,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
634
634
  readonly [Tag in Instantiate<F>["_tag"]]?: (
635
635
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
636
636
  ) => R;
637
- } & { _: (adt: ApplyHKT<F, [T]>) => R },
637
+ } & { _: (adt: ApplyHKT<F, [T]>) => R }
638
638
  ): (adt: ApplyHKT<F, [T]>) => R;
639
639
  }
640
640
  : {
@@ -644,7 +644,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
644
644
  readonly [Tag in Instantiate<F>["_tag"]]: (
645
645
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
646
646
  ) => R;
647
- },
647
+ }
648
648
  ): R;
649
649
  <T extends HKTParams<F>[0], R>(
650
650
  adt: ApplyHKT<F, [T]>,
@@ -652,7 +652,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
652
652
  readonly [Tag in Instantiate<F>["_tag"]]?: (
653
653
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
654
654
  ) => R;
655
- } & { _: (adt: ApplyHKT<F, [T]>) => R },
655
+ } & { _: (adt: ApplyHKT<F, [T]>) => R }
656
656
  ): R;
657
657
  <T extends HKTParams<F>[0], R>(cases: {
658
658
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -664,7 +664,7 @@ type Matcher1<F extends TypeLambda<[never], Tagged>> =
664
664
  readonly [Tag in Instantiate<F>["_tag"]]?: (
665
665
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T]>, Tag>>
666
666
  ) => R;
667
- } & { _: (adt: ApplyHKT<F, [T]>) => R },
667
+ } & { _: (adt: ApplyHKT<F, [T]>) => R }
668
668
  ): (adt: ApplyHKT<F, [T]>) => R;
669
669
  };
670
670
 
@@ -677,7 +677,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
677
677
  readonly [Tag in Instantiate<F>["_tag"]]: (
678
678
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
679
679
  ) => R;
680
- },
680
+ }
681
681
  ): R;
682
682
  <T, U, R>(
683
683
  adt: ApplyHKT<F, [T, U]>,
@@ -685,7 +685,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
685
685
  readonly [Tag in Instantiate<F>["_tag"]]?: (
686
686
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
687
687
  ) => R;
688
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
688
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
689
689
  ): R;
690
690
  <T, U, R>(cases: {
691
691
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -697,7 +697,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
697
697
  readonly [Tag in Instantiate<F>["_tag"]]?: (
698
698
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
699
699
  ) => R;
700
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
700
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
701
701
  ): (adt: ApplyHKT<F, [T, U]>) => R;
702
702
  }
703
703
  : unknown extends HKTParams<F>[0] ?
@@ -708,7 +708,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
708
708
  readonly [Tag in Instantiate<F>["_tag"]]: (
709
709
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
710
710
  ) => R;
711
- },
711
+ }
712
712
  ): R;
713
713
  <T, U extends HKTParams<F>[1], R>(
714
714
  adt: ApplyHKT<F, [T, U]>,
@@ -716,7 +716,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
716
716
  readonly [Tag in Instantiate<F>["_tag"]]?: (
717
717
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
718
718
  ) => R;
719
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
719
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
720
720
  ): R;
721
721
  <T, U extends HKTParams<F>[1], R>(cases: {
722
722
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -728,7 +728,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
728
728
  readonly [Tag in Instantiate<F>["_tag"]]?: (
729
729
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
730
730
  ) => R;
731
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
731
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
732
732
  ): (adt: ApplyHKT<F, [T, U]>) => R;
733
733
  }
734
734
  : unknown extends HKTParams<F>[1] ?
@@ -739,7 +739,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
739
739
  readonly [Tag in Instantiate<F>["_tag"]]: (
740
740
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
741
741
  ) => R;
742
- },
742
+ }
743
743
  ): R;
744
744
  <T extends HKTParams<F>[0], U, R>(
745
745
  adt: ApplyHKT<F, [T, U]>,
@@ -747,7 +747,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
747
747
  readonly [Tag in Instantiate<F>["_tag"]]?: (
748
748
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
749
749
  ) => R;
750
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
750
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
751
751
  ): R;
752
752
  <T extends HKTParams<F>[0], U, R>(cases: {
753
753
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -759,7 +759,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
759
759
  readonly [Tag in Instantiate<F>["_tag"]]?: (
760
760
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
761
761
  ) => R;
762
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
762
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
763
763
  ): (adt: ApplyHKT<F, [T, U]>) => R;
764
764
  }
765
765
  : {
@@ -769,7 +769,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
769
769
  readonly [Tag in Instantiate<F>["_tag"]]: (
770
770
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
771
771
  ) => R;
772
- },
772
+ }
773
773
  ): R;
774
774
  <T extends HKTParams<F>[0], U extends HKTParams<F>[1], R>(
775
775
  adt: ApplyHKT<F, [T, U]>,
@@ -777,7 +777,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
777
777
  readonly [Tag in Instantiate<F>["_tag"]]?: (
778
778
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
779
779
  ) => R;
780
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
780
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
781
781
  ): R;
782
782
  <T extends HKTParams<F>[0], U extends HKTParams<F>[1], R>(cases: {
783
783
  readonly [Tag in Instantiate<F>["_tag"]]: (
@@ -789,7 +789,7 @@ type Matcher2<F extends TypeLambda<[never, never], Tagged>> =
789
789
  readonly [Tag in Instantiate<F>["_tag"]]?: (
790
790
  ...args: ExtractFields<FilterTagged<ApplyHKT<F, [T, U]>, Tag>>
791
791
  ) => R;
792
- } & { _: (adt: ApplyHKT<F, [T, U]>) => R },
792
+ } & { _: (adt: ApplyHKT<F, [T, U]>) => R }
793
793
  ): (adt: ApplyHKT<F, [T, U]>) => R;
794
794
  };
795
795
 
@@ -804,7 +804,7 @@ export interface Matcher<Type extends Tagged> {
804
804
  readonly [Tag in Type["_tag"]]: (
805
805
  ...args: ExtractFields<FilterTagged<T, Tag>>
806
806
  ) => R;
807
- },
807
+ }
808
808
  ): R;
809
809
  <T extends Type, R>(
810
810
  adt: T,
@@ -812,7 +812,7 @@ export interface Matcher<Type extends Tagged> {
812
812
  readonly [Tag in Type["_tag"]]?: (
813
813
  ...args: ExtractFields<FilterTagged<T, Tag>>
814
814
  ) => R;
815
- } & { _: (adt: T) => R },
815
+ } & { _: (adt: T) => R }
816
816
  ): R;
817
817
  <T extends Type, R>(cases: {
818
818
  readonly [Tag in Type["_tag"]]: (
@@ -824,7 +824,7 @@ export interface Matcher<Type extends Tagged> {
824
824
  readonly [Tag in Type["_tag"]]?: (
825
825
  ...args: ExtractFields<FilterTagged<T, Tag>>
826
826
  ) => R;
827
- } & { _: (adt: T) => R },
827
+ } & { _: (adt: T) => R }
828
828
  ): (adt: T) => R;
829
829
  }
830
830
 
@@ -839,7 +839,7 @@ type MatcherOfW<F extends Tagged | TypeLambda<never, Tagged>> =
839
839
  },
840
840
  >(
841
841
  adt: F,
842
- cases: Cases,
842
+ cases: Cases
843
843
  ): ReturnType<ValueOf<Cases>>;
844
844
  <
845
845
  Cases extends {
@@ -849,7 +849,7 @@ type MatcherOfW<F extends Tagged | TypeLambda<never, Tagged>> =
849
849
  } & { _: (adt: F) => unknown },
850
850
  >(
851
851
  adt: F,
852
- cases: Cases,
852
+ cases: Cases
853
853
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
854
854
  <
855
855
  Cases extends {
@@ -858,7 +858,7 @@ type MatcherOfW<F extends Tagged | TypeLambda<never, Tagged>> =
858
858
  ) => unknown;
859
859
  },
860
860
  >(
861
- cases: Cases,
861
+ cases: Cases
862
862
  ): (adt: F) => ReturnType<ValueOf<Cases>>;
863
863
  <
864
864
  Cases extends {
@@ -867,9 +867,9 @@ type MatcherOfW<F extends Tagged | TypeLambda<never, Tagged>> =
867
867
  ) => unknown;
868
868
  } & { _: (adt: F) => unknown },
869
869
  >(
870
- cases: Cases,
870
+ cases: Cases
871
871
  ): (
872
- adt: F,
872
+ adt: F
873
873
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
874
874
  }
875
875
  : [F] extends [TypeLambda<[never], Tagged>] ? Matcher1W<F>
@@ -889,7 +889,7 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
889
889
  },
890
890
  >(
891
891
  adt: ApplyHKT<F, [T]>,
892
- cases: Cases,
892
+ cases: Cases
893
893
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
894
894
  <
895
895
  T,
@@ -901,7 +901,7 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
901
901
  } & { _: (adt: ApplyHKT<F, [T]>) => R },
902
902
  >(
903
903
  adt: ApplyHKT<F, [T]>,
904
- cases: Cases,
904
+ cases: Cases
905
905
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
906
906
  <
907
907
  T,
@@ -912,9 +912,9 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
912
912
  ) => unknown;
913
913
  },
914
914
  >(
915
- cases: Cases,
915
+ cases: Cases
916
916
  ): (
917
- adt: ApplyHKT<F, [T]>,
917
+ adt: ApplyHKT<F, [T]>
918
918
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
919
919
  <
920
920
  T,
@@ -925,9 +925,9 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
925
925
  ) => R;
926
926
  } & { _: (adt: ApplyHKT<F, [T]>) => R },
927
927
  >(
928
- cases: Cases,
928
+ cases: Cases
929
929
  ): (
930
- adt: ApplyHKT<F, [T]>,
930
+ adt: ApplyHKT<F, [T]>
931
931
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
932
932
  }
933
933
  : {
@@ -940,7 +940,7 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
940
940
  },
941
941
  >(
942
942
  adt: T,
943
- cases: Cases,
943
+ cases: Cases
944
944
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
945
945
  <
946
946
  T extends HKTParams<F>[0],
@@ -951,7 +951,7 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
951
951
  } & { _: (adt: ApplyHKT<F, [T]>) => unknown },
952
952
  >(
953
953
  adt: ApplyHKT<F, [T]>,
954
- cases: Cases,
954
+ cases: Cases
955
955
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
956
956
  <
957
957
  T extends HKTParams<F>[0],
@@ -961,9 +961,9 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
961
961
  ) => unknown;
962
962
  },
963
963
  >(
964
- cases: Cases,
964
+ cases: Cases
965
965
  ): (
966
- adt: ApplyHKT<F, [T]>,
966
+ adt: ApplyHKT<F, [T]>
967
967
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
968
968
  <
969
969
  T extends HKTParams<F>[0],
@@ -973,9 +973,9 @@ type Matcher1W<F extends TypeLambda<[never], Tagged>> =
973
973
  ) => unknown;
974
974
  } & { _: (adt: ApplyHKT<F, [T]>) => unknown },
975
975
  >(
976
- cases: Cases,
976
+ cases: Cases
977
977
  ): (
978
- adt: ApplyHKT<F, [T]>,
978
+ adt: ApplyHKT<F, [T]>
979
979
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
980
980
  };
981
981
 
@@ -992,7 +992,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
992
992
  },
993
993
  >(
994
994
  adt: ApplyHKT<F, [T, U]>,
995
- cases: Cases,
995
+ cases: Cases
996
996
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
997
997
  <
998
998
  T,
@@ -1004,7 +1004,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1004
1004
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1005
1005
  >(
1006
1006
  adt: ApplyHKT<F, [T, U]>,
1007
- cases: Cases,
1007
+ cases: Cases
1008
1008
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1009
1009
  <
1010
1010
  T,
@@ -1015,9 +1015,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1015
1015
  ) => unknown;
1016
1016
  },
1017
1017
  >(
1018
- cases: Cases,
1018
+ cases: Cases
1019
1019
  ): (
1020
- adt: ApplyHKT<F, [T, U]>,
1020
+ adt: ApplyHKT<F, [T, U]>
1021
1021
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1022
1022
  <
1023
1023
  T,
@@ -1028,9 +1028,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1028
1028
  ) => unknown;
1029
1029
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1030
1030
  >(
1031
- cases: Cases,
1031
+ cases: Cases
1032
1032
  ): (
1033
- adt: ApplyHKT<F, [T, U]>,
1033
+ adt: ApplyHKT<F, [T, U]>
1034
1034
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1035
1035
  }
1036
1036
  : unknown extends HKTParams<F>[0] ?
@@ -1045,7 +1045,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1045
1045
  },
1046
1046
  >(
1047
1047
  adt: ApplyHKT<F, [T, U]>,
1048
- cases: Cases,
1048
+ cases: Cases
1049
1049
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1050
1050
  <
1051
1051
  T,
@@ -1057,7 +1057,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1057
1057
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1058
1058
  >(
1059
1059
  adt: ApplyHKT<F, [T, U]>,
1060
- cases: Cases,
1060
+ cases: Cases
1061
1061
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1062
1062
  <
1063
1063
  T,
@@ -1068,9 +1068,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1068
1068
  ) => unknown;
1069
1069
  },
1070
1070
  >(
1071
- cases: Cases,
1071
+ cases: Cases
1072
1072
  ): (
1073
- adt: ApplyHKT<F, [T, U]>,
1073
+ adt: ApplyHKT<F, [T, U]>
1074
1074
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1075
1075
  <
1076
1076
  T,
@@ -1081,9 +1081,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1081
1081
  ) => unknown;
1082
1082
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1083
1083
  >(
1084
- cases: Cases,
1084
+ cases: Cases
1085
1085
  ): (
1086
- adt: ApplyHKT<F, [T, U]>,
1086
+ adt: ApplyHKT<F, [T, U]>
1087
1087
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1088
1088
  }
1089
1089
  : unknown extends HKTParams<F>[1] ?
@@ -1098,7 +1098,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1098
1098
  },
1099
1099
  >(
1100
1100
  adt: ApplyHKT<F, [T, U]>,
1101
- cases: Cases,
1101
+ cases: Cases
1102
1102
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1103
1103
  <
1104
1104
  T extends HKTParams<F>[0],
@@ -1110,7 +1110,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1110
1110
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1111
1111
  >(
1112
1112
  adt: ApplyHKT<F, [T, U]>,
1113
- cases: Cases,
1113
+ cases: Cases
1114
1114
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1115
1115
  <
1116
1116
  T extends HKTParams<F>[0],
@@ -1121,9 +1121,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1121
1121
  ) => unknown;
1122
1122
  },
1123
1123
  >(
1124
- cases: Cases,
1124
+ cases: Cases
1125
1125
  ): (
1126
- adt: ApplyHKT<F, [T, U]>,
1126
+ adt: ApplyHKT<F, [T, U]>
1127
1127
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1128
1128
  <
1129
1129
  T extends HKTParams<F>[0],
@@ -1134,9 +1134,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1134
1134
  ) => unknown;
1135
1135
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1136
1136
  >(
1137
- cases: Cases,
1137
+ cases: Cases
1138
1138
  ): (
1139
- adt: ApplyHKT<F, [T, U]>,
1139
+ adt: ApplyHKT<F, [T, U]>
1140
1140
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1141
1141
  }
1142
1142
  : {
@@ -1150,7 +1150,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1150
1150
  },
1151
1151
  >(
1152
1152
  adt: ApplyHKT<F, [T, U]>,
1153
- cases: Cases,
1153
+ cases: Cases
1154
1154
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1155
1155
  <
1156
1156
  T extends HKTParams<F>[0],
@@ -1162,7 +1162,7 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1162
1162
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1163
1163
  >(
1164
1164
  adt: ApplyHKT<F, [T, U]>,
1165
- cases: Cases,
1165
+ cases: Cases
1166
1166
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1167
1167
  <
1168
1168
  T extends HKTParams<F>[0],
@@ -1173,9 +1173,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1173
1173
  ) => unknown;
1174
1174
  },
1175
1175
  >(
1176
- cases: Cases,
1176
+ cases: Cases
1177
1177
  ): (
1178
- adt: ApplyHKT<F, [T, U]>,
1178
+ adt: ApplyHKT<F, [T, U]>
1179
1179
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1180
1180
  <
1181
1181
  T extends HKTParams<F>[0],
@@ -1186,9 +1186,9 @@ type Matcher2W<F extends TypeLambda<[never, never], Tagged>> =
1186
1186
  ) => unknown;
1187
1187
  } & { _: (adt: ApplyHKT<F, [T, U]>) => unknown },
1188
1188
  >(
1189
- cases: Cases,
1189
+ cases: Cases
1190
1190
  ): (
1191
- adt: ApplyHKT<F, [T, U]>,
1191
+ adt: ApplyHKT<F, [T, U]>
1192
1192
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1193
1193
  };
1194
1194
 
@@ -1206,7 +1206,7 @@ export interface MatcherW<Type extends Tagged> {
1206
1206
  },
1207
1207
  >(
1208
1208
  adt: T,
1209
- cases: Cases,
1209
+ cases: Cases
1210
1210
  ): ReturnType<ValueOf<Cases>>;
1211
1211
  <
1212
1212
  T extends Type,
@@ -1217,7 +1217,7 @@ export interface MatcherW<Type extends Tagged> {
1217
1217
  } & { _: (adt: T) => unknown },
1218
1218
  >(
1219
1219
  adt: T,
1220
- cases: Cases,
1220
+ cases: Cases
1221
1221
  ): ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1222
1222
  <
1223
1223
  T extends Type,
@@ -1227,7 +1227,7 @@ export interface MatcherW<Type extends Tagged> {
1227
1227
  ) => unknown;
1228
1228
  },
1229
1229
  >(
1230
- cases: Cases,
1230
+ cases: Cases
1231
1231
  ): (adt: T) => ReturnType<ValueOf<Cases>>;
1232
1232
  <
1233
1233
  T extends Type,
@@ -1237,9 +1237,9 @@ export interface MatcherW<Type extends Tagged> {
1237
1237
  ) => unknown;
1238
1238
  } & { _: (adt: T) => unknown },
1239
1239
  >(
1240
- cases: Cases,
1240
+ cases: Cases
1241
1241
  ): (
1242
- adt: T,
1242
+ adt: T
1243
1243
  ) => ReturnType<Extract<ValueOf<Cases>, (...args: never) => unknown>>;
1244
1244
  }
1245
1245
 
package/index.js CHANGED
@@ -21,28 +21,29 @@ export function make(variants) {
21
21
  renameFunction((adt) => {
22
22
  if (adt == null || adt._tag !== tag)
23
23
  throw new TypeError(
24
- `Expected \`${tag}(...)\`, but got \`${stringify(adt)}\``,
24
+ `Expected \`${tag}(...)\`, but got \`${stringify(adt)}\``
25
25
  );
26
26
  return unwrap(adt);
27
27
  }, `unwrap${tag}`);
28
28
 
29
29
  /* Constructor */
30
- const createConstructor = (tag) => {
31
- const result = Object.create(PipeableProto);
32
- result._tag = tag;
33
- result.toJSON = () => ({ _tag: tag });
34
- result[Symbol.for("nodejs.util.inspect.custom")] = () => ({ _tag: tag });
35
-
36
- return Object.assign(
37
- renameFunction((...args) => {
38
- const result = Object.create(PipeableProto);
39
- result._tag = tag;
40
- for (let i = 0; i < args.length; i++) result["_" + i] = args[i];
41
- return result;
42
- }, tag),
43
- result,
30
+ const createConstructor = (tag) =>
31
+ Object.setPrototypeOf(
32
+ Object.assign(
33
+ renameFunction((...args) => {
34
+ const result = Object.create(ADTProto);
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
+ ADTConstructorProto
44
46
  );
45
- };
46
47
 
47
48
  const result = {
48
49
  unwrap:
@@ -50,12 +51,12 @@ export function make(variants) {
50
51
  function unwrap(adt) {
51
52
  if (adt == null || variants.indexOf(adt._tag) === -1)
52
53
  throw new TypeError(
53
- `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``,
54
+ `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``
54
55
  );
55
56
  return entriesOf(adt)
56
57
  .filter(
57
58
  ([key]) =>
58
- key.startsWith("_") && !Object.is(Number(key.slice(1)), NaN),
59
+ key.startsWith("_") && !Object.is(Number(key.slice(1)), NaN)
59
60
  )
60
61
  .sort(([a], [b]) => Number(a.slice(1)) - Number(b.slice(1)))
61
62
  .map(([, value]) => value);
@@ -70,14 +71,14 @@ export function make(variants) {
70
71
  return function match(adt) {
71
72
  if (adt == null || variants.indexOf(adt._tag) === -1)
72
73
  throw new TypeError(
73
- `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``,
74
+ `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``
74
75
  );
75
76
  return _match(adt, cases);
76
77
  };
77
78
  }
78
79
  if (adt == null || variants.indexOf(adt._tag) === -1)
79
80
  throw new TypeError(
80
- `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``,
81
+ `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``
81
82
  );
82
83
  return _match(adt, cases);
83
84
  }
@@ -98,14 +99,14 @@ export function make(variants) {
98
99
  return function matchW(adt) {
99
100
  if (adt == null || variants.indexOf(adt._tag) === -1)
100
101
  throw new TypeError(
101
- `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``,
102
+ `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``
102
103
  );
103
104
  return _match(adt, cases);
104
105
  };
105
106
  }
106
107
  if (adt == null || variants.indexOf(adt._tag) === -1)
107
108
  throw new TypeError(
108
- `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``,
109
+ `Expected ${variants.map((tag) => "`" + tag + "(...)`").join("/")}, but got \`${stringify(adt)}\``
109
110
  );
110
111
  return _match(adt, cases);
111
112
  }
@@ -174,7 +175,7 @@ export function make(variants) {
174
175
  export function unwrap(adt) {
175
176
  return entriesOf(adt)
176
177
  .filter(
177
- ([key]) => key.startsWith("_") && !Object.is(Number(key.slice(1)), NaN),
178
+ ([key]) => key.startsWith("_") && !Object.is(Number(key.slice(1)), NaN)
178
179
  )
179
180
  .sort(([a], [b]) => Number(a.slice(1)) - Number(b.slice(1)))
180
181
  .map(([, value]) => value);
@@ -192,7 +193,7 @@ function _match(adt, cases) {
192
193
  if (adt != null && cases[adt._tag]) return cases[adt._tag](...unwrap(adt));
193
194
  if (cases._) return cases._(adt);
194
195
  throw new Error(
195
- `No case found for \`${stringify(adt)}\`. Consider adding a catch-all case (\`_\`) if needed`,
196
+ `No case found for \`${stringify(adt)}\`. Consider adding a catch-all case (\`_\`) if needed`
196
197
  );
197
198
  }
198
199
 
@@ -228,6 +229,22 @@ function matchesPrefix(str, prefix) {
228
229
  /****************************
229
230
  * Common utility functions *
230
231
  ****************************/
232
+ /**
233
+ * A polyfill for `Array#flatMap` to support pre ES2019 environments.
234
+ * @param arr The array to flatten.
235
+ * @param fn The function to call on each element of the array.
236
+ * @returns
237
+ */
238
+ function flatMap(arr, fn) {
239
+ const result = [];
240
+ for (let i = 0; i < arr.length; i++) {
241
+ const value = fn(arr[i], i, arr);
242
+ if (Array.isArray(value)) Array.prototype.push.apply(result, value);
243
+ else result.push(value);
244
+ }
245
+ return result;
246
+ }
247
+
231
248
  /**
232
249
  * Get the entries of an object.
233
250
  * @private
@@ -295,7 +312,7 @@ const stringify = (value) => {
295
312
  const entries = Array.from(value.entries())
296
313
  .map(
297
314
  ([k, v]) =>
298
- `${serialize(k, nextAncestors)} => ${serialize(v, nextAncestors)}`,
315
+ `${serialize(k, nextAncestors)} => ${serialize(v, nextAncestors)}`
299
316
  )
300
317
  .join(", ");
301
318
  return `Map(${value.size}) ` + (entries ? `{ ${entries} }` : "{}");
@@ -328,7 +345,7 @@ const stringify = (value) => {
328
345
  const objectEntries = Reflect.ownKeys(value)
329
346
  .map((key) => {
330
347
  const keyDisplay =
331
- typeof key === "symbol" ? `[${key.toString()}]`
348
+ typeof key === "symbol" ? key.toString()
332
349
  : identifierRegex.test(key) ? key
333
350
  : JSON.stringify(key);
334
351
  const val = value[key];
@@ -348,6 +365,75 @@ const stringify = (value) => {
348
365
  return serialize(value, []);
349
366
  };
350
367
 
368
+ /**
369
+ * Custom inspect function for ADT to interact with the
370
+ * [showify](https://github.com/Snowflyt/showify) package.
371
+ * @returns
372
+ */
373
+ function inspect({ ancestors, c, level }, expand) {
374
+ const fields = unwrap(this);
375
+ const fieldKeys = fields.map((_, i) => `_${i}`);
376
+
377
+ let body = expand(this, {
378
+ level,
379
+ omittedKeys: new Set([
380
+ "_tag",
381
+ ...fieldKeys,
382
+ "toJSON",
383
+ Symbol.for("nodejs.util.inspect.custom"),
384
+ Symbol.for("showify.inspect.custom"),
385
+ ]),
386
+ ancestors,
387
+ });
388
+ if (
389
+ body.type === "sequence" &&
390
+ body.values[0].type === "text" &&
391
+ body.values[0].value.startsWith("[Function")
392
+ ) {
393
+ body.values[2].ref = body.ref;
394
+ body = body.values[2];
395
+ }
396
+
397
+ return (
398
+ fields.length ?
399
+ variant(
400
+ sequence([
401
+ text(c.cyan(this._tag) + "("),
402
+ ...flatMap(fields, (field, i, arr) =>
403
+ i === arr.length - 1 ? expand(field) : [expand(field), text(", ")]
404
+ ),
405
+ ...(body.type === "text" ? [text(")")] : [text(") "), body]),
406
+ ]),
407
+ 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(
415
+ fields.map((field) => pair(expand(field), text(","))),
416
+ text(c.cyan(this._tag) + "("),
417
+ text(") ")
418
+ ),
419
+ body
420
+ )
421
+ )
422
+ : body.type === "text" ? text(c.cyan(this._tag))
423
+ : pair(text(c.cyan(this._tag) + " "), body)
424
+ );
425
+ }
426
+ const text = (value) => ({ type: "text", value });
427
+ const variant = (inline, wrap) => ({ type: "variant", inline, wrap });
428
+ const sequence = (values) => ({ type: "sequence", values });
429
+ const pair = (left, right) => sequence([left, right]);
430
+ const between = (values, open, close) => ({
431
+ type: "between",
432
+ values,
433
+ open,
434
+ close,
435
+ });
436
+
351
437
  export const PipeableProto = {
352
438
  pipe(...fs) {
353
439
  // Optimization inspired by Effect
@@ -373,7 +459,7 @@ export const PipeableProto = {
373
459
  return fs[7](fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this))))))));
374
460
  case 9:
375
461
  return fs[8](
376
- fs[7](fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this)))))))),
462
+ fs[7](fs[6](fs[5](fs[4](fs[3](fs[2](fs[1](fs[0](this))))))))
377
463
  );
378
464
  default: {
379
465
  let result = this;
@@ -383,3 +469,11 @@ export const PipeableProto = {
383
469
  }
384
470
  },
385
471
  };
472
+
473
+ const ADTProto = {
474
+ ...PipeableProto,
475
+ [Symbol.for("showify.inspect.custom")]: inspect,
476
+ };
477
+
478
+ const ADTConstructorProto = { ...ADTProto };
479
+ Object.setPrototypeOf(ADTConstructorProto, Function.prototype);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kind-adt",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "🪴 The kind of ADTs you can count on in TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
@@ -24,13 +24,5 @@
24
24
  "type": "module",
25
25
  "main": "./index.js",
26
26
  "module": "./index.js",
27
- "types": "./index.d.ts",
28
- "peerDependencies": {
29
- "showify": ">=0.1"
30
- },
31
- "peerDependenciesMeta": {
32
- "showify": {
33
- "optional": true
34
- }
35
- }
27
+ "types": "./index.d.ts"
36
28
  }
package/utils.d.ts DELETED
@@ -1,59 +0,0 @@
1
- import type { ShowOptions } from "showify";
2
-
3
- /**
4
- * Print arguments including (possibly) ADTs to `stdout` with newline.
5
- * @param args The arguments to print.
6
- *
7
- * @example
8
- * ```typescript
9
- * // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
10
- * const tree = Tree.Node(
11
- * 1,
12
- * Tree.Node(2, Tree.Node(3, Tree.Empty, Tree.Empty), Tree.Empty),
13
- * Tree.Node(4, Tree.Empty, Tree.Node(3, Tree.Empty, Tree.Empty)),
14
- * );
15
- *
16
- * // ANSI colors are supported
17
- * println(tree);
18
- * // Node(
19
- * // 1,
20
- * // Node(2, Node(3, Empty, Empty), Empty),
21
- * // Node(4, Empty, Node(3, Empty, Empty))
22
- * // )
23
- * ```
24
- *
25
- * @see {@linkcode show} if you want more control over the output.
26
- */
27
- export declare function println(...args: unknown[]): void;
28
-
29
- /**
30
- * Stringify a (possibly) ADT to human-readable format.
31
- * @param value The value to stringify.
32
- * @param options The options for stringification.
33
- * @returns
34
- *
35
- * @example
36
- * ```typescript
37
- * // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
38
- * const tree = Tree.Node(
39
- * 1,
40
- * Tree.Node(2, Tree.Empty, Tree.Empty),
41
- * Tree.Empty,
42
- * );
43
- *
44
- * console.log(show(tree));
45
- * // Node(1, Node(2, Empty, Empty), Empty)
46
- *
47
- * console.log(show(tree, { indent: 4, breakLength: 0, trailingComma: "auto" }));
48
- * // Node(
49
- * // 1,
50
- * // Node(
51
- * // 2,
52
- * // Empty,
53
- * // Empty,
54
- * // ),
55
- * // Empty,
56
- * // )
57
- * ```
58
- */
59
- export declare function show(value: unknown, options?: ShowOptions): string;
package/utils.js DELETED
@@ -1,168 +0,0 @@
1
- import { Node as SerializerNode, serializer, show as stringify } from "showify";
2
-
3
- import { unwrap } from "./index.js";
4
-
5
- const { between, pair, sequence, text, variant } = SerializerNode;
6
-
7
- /**
8
- * Print arguments including (possibly) ADTs to `stdout` with newline.
9
- * @param args The arguments to print.
10
- *
11
- * @example
12
- * ```typescript
13
- * // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
14
- * const tree = Tree.Node(
15
- * 1,
16
- * Tree.Node(2, Tree.Node(3, Tree.Empty, Tree.Empty), Tree.Empty),
17
- * Tree.Node(4, Tree.Empty, Tree.Node(3, Tree.Empty, Tree.Empty)),
18
- * );
19
- *
20
- * // ANSI colors are supported
21
- * println(tree);
22
- * // Node(
23
- * // 1,
24
- * // Node(2, Node(3, Empty, Empty), Empty),
25
- * // Node(4, Empty, Node(3, Empty, Empty))
26
- * // )
27
- * ```
28
- *
29
- * @see {@linkcode show} if you want more control over the output.
30
- */
31
- export function println(...args) {
32
- getConsole().log(
33
- ...args.map((arg) => (typeof arg === "string" ? arg : show(arg, { colors: true, indent: 2 }))),
34
- );
35
- }
36
-
37
- /**
38
- * Stringify a (possibly) ADT to human-readable format.
39
- * @param value The value to stringify.
40
- * @param options The options for stringification.
41
- * @returns
42
- *
43
- * @example
44
- * ```typescript
45
- * // Suppose we have an ADT `data Tree<T> = Empty | Node(T, Tree<T>, Tree<T>)`
46
- * const tree = Tree.Node(
47
- * 1,
48
- * Tree.Node(2, Tree.Empty, Tree.Empty),
49
- * Tree.Empty,
50
- * );
51
- *
52
- * console.log(show(tree));
53
- * // Node(1, Node(2, Empty, Empty), Empty)
54
- *
55
- * console.log(show(tree, { indent: 4, breakLength: 0, trailingComma: "auto" }));
56
- * // Node(
57
- * // 1,
58
- * // Node(
59
- * // 2,
60
- * // Empty,
61
- * // Empty,
62
- * // ),
63
- * // Empty,
64
- * // )
65
- * ```
66
- */
67
- export function show(value, options = {}) {
68
- return stringify(value, {
69
- ...options,
70
- serializers: [
71
- serializer({
72
- if: (value, { omittedKeys }) =>
73
- "_tag" in value &&
74
- typeof value._tag === "string" &&
75
- // Detect if `_tag` is already omitted to avoid infinite recursion
76
- !omittedKeys.has("_tag"),
77
- then: (val, { ancestors, c, level }, expand) => {
78
- const fields = unwrap(val);
79
- const fieldKeys = fields.map((_, i) => `_${i}`);
80
-
81
- let body = expand(val, {
82
- level,
83
- omittedKeys: new Set([
84
- "_tag",
85
- ...fieldKeys,
86
- "toJSON",
87
- Symbol.for("nodejs.util.inspect.custom"),
88
- ]),
89
- ancestors,
90
- });
91
- if (
92
- body.type === "sequence" &&
93
- body.values[0].type === "text" &&
94
- body.values[0].value.startsWith("[Function")
95
- ) {
96
- body.values[2].ref = body.ref;
97
- body = body.values[2];
98
- }
99
-
100
- return (
101
- fields.length ?
102
- variant(
103
- sequence([
104
- text(c.cyan(val._tag) + "("),
105
- ...flatMap(fields, (field, i, arr) =>
106
- i === arr.length - 1 ? expand(field) : [expand(field), text(", ")],
107
- ),
108
- ...(body.type === "text" ? [text(")")] : [text(") "), body]),
109
- ]),
110
- body.type === "text" ?
111
- between(
112
- fields.map((field) => pair(expand(field), text(","))),
113
- text(c.cyan(val._tag) + "("),
114
- text(")"),
115
- )
116
- : pair(
117
- between(
118
- fields.map((field) => pair(expand(field), text(","))),
119
- text(c.cyan(val._tag) + "("),
120
- text(") "),
121
- ),
122
- body,
123
- ),
124
- )
125
- : body.type === "text" ? text(c.cyan(val._tag))
126
- : pair(text(c.cyan(val._tag) + " "), body)
127
- );
128
- },
129
- }),
130
- ...(options.serializers || []),
131
- ],
132
- });
133
- }
134
-
135
- /****************************
136
- * Common utility functions *
137
- ****************************/
138
- /**
139
- * A polyfill for `Array#flatMap` to support pre ES2019 environments.
140
- * @param arr The array to flatten.
141
- * @param fn The function to call on each element of the array.
142
- * @returns
143
- */
144
- const flatMap = (arr, fn) => {
145
- const result = [];
146
- for (let i = 0; i < arr.length; i++) {
147
- const value = fn(arr[i], i, arr);
148
- if (Array.isArray(value)) Array.prototype.push.apply(result, value);
149
- else result.push(value);
150
- }
151
- return result;
152
- };
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
- })();