rivo
v0.0.0-dev.20240701
Published
🤖 The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.
Downloads
254
Maintainers
Readme
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