0.0.0-dev.20240701 • Published 1 year ago

rivo v0.0.0-dev.20240701

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

Rivo

The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.

import type { $, Ask, Flow, List, Num, Ord, Pipe, Show, Sig, Some, Str, Tuple$$Of1 } from "rivo";

// Rivo provides out-of-the-box type level functions, following point-free style
type R1 = Pipe<[-1, 0, 1], List.Every<Num.IsPos>>;
//   ^?: false
type R2 = Pipe<123, Show.Show, Str.ToChars, List.Every<Str.IsDigit>>;
//   ^?: true

// These functions can be called using `$` (`Call`) or `Apply`,
// or `Pipe` if it accepts only one argument (as you can see above)
type R3 = $<Str.Length, "foo">;
//   ^?: 3
type IsEveryPositive = List.Every<Num.IsPos>;
type R4 = $<IsEveryPositive, [1, 2, 3]>;
//   ^?: true
type R5 = $<Str.Concat, "foo", "bar">;
//   ^?: "foobar"
type R6 = $<Str.Append<"bar">, "foo">;
//   ^?: "foobar"

// Use `Sig` to get the signature of a type level function (for debugging)
type IsEveryPositiveSig = Sig<IsEveryPositive>;

// Type safety is **guaranteed** when using `$` and `Call`
type R7 = $<Str.Append<"foo">, 123>;
//                             ~~~
//      Type 'number' does not satisfy the constraint 'string'
type R8 = $<Str.Append<"foo">, "bar", "baz">;
//                                    ~~~~~
//                Type 'string' does not satisfy the constraint 'never'
type Append42 = Str.Append<42>;
//                         ~~
// Type 'number' does not satisfy the constraint 'string'

// You can easily combine multiple type level functions into one using `Flow`
type IsNaturalNumberFn = Flow<Show.Show, Str.ToChars, List.Every<Str.IsDigit>>;

type R9 = $<IsNaturalNumberFn, 123>;
//   ^?: true
type R10 = $<IsNaturalNumberFn, 123.5>;
//   ^?: false

// Type safety is **still guaranteed** even when using `Flow` and `Pipe`
type F1 = Flow<Show.Show, List.Every<Num.IsPos>>;
//                        ~~~~~~~~~~~~~~~~~~~~~
//       Type 'string' is not assignable to type 'List<number>'
type R11 = Pipe<"123", Str.ToChars, List.Map<Num.IsPos>>;
//                                  ~~~~~~~~~~~~~~~~~~~
//                    Type 'string' is not assignable to type 'number'

// Type level functions can be even generic (see `GenericFn` and `GenericResolver` for more info)
type R12 = Sig<Flow<Ask<number>, Tuple$$Of1>>;
//   ^?: (n: number) => readonly [number]
type R13 = Sig<Flow<Ask<string>, Tuple$$Of1>>;
//   ^?: (n: string) => readonly [string] <- Changes based on the input type

// Even type-level type classes! CRAZY! (see inside `rivo/typeclass` for more info)
type R14 = $<Ord.Compare, 1, 2>;
//   ^?: -1
type R15 = $<Ord.Compare, Some<42>, Some<43>>;
//   ^?: -1
type R16 = $<Ord.Compare, Some<Some<55>>, Some<Some<55>>>;
//   ^?: 0

Build your own type level functions with ease.

import type { $, Args, Call2, Fn, PartialApply } from "rivo";
import type { Dec } from "rivo/Num/Int/Dec";

interface RepeatStringFn extends Fn<[number, string], string> {
  def: ([n, s]: Args<this>) => typeof n extends 0 ? ""
  : `${typeof s}${Call2<RepeatStringFn, Dec<typeof n>, typeof s>}`;
}

type R1 = $<RepeatStringFn, 3, "foo">;
//   ^?: "foofoofoo"

// You can partial apply the function to create a new function
type RepeatString<N extends number> = PartialApply<RepeatStringFn, [N]>;

type R2 = $<RepeatString<3>, "foo">;
//   ^?: "foofoofoo"

... and much more! Rivo provides great documentation and examples to get you started, just explore them!

Note: Rivo requires TypeScript 5.0 or above.

Installation

npm install --save-dev rivo
# Or
yarn add -D rivo
# Or
pnpm add -D rivo
# Or
bun install --dev rivo